5 use crate::pp
::Breaks
::{Consistent, Inconsistent}
;
6 use crate::pp
::{self, Breaks}
;
9 use rustc_ast
::token
::{self, BinOpToken, CommentKind, DelimToken, Nonterminal, Token, TokenKind}
;
10 use rustc_ast
::tokenstream
::{TokenStream, TokenTree}
;
11 use rustc_ast
::util
::classify
;
12 use rustc_ast
::util
::comments
::{gather_comments, Comment, CommentStyle}
;
13 use rustc_ast
::util
::parser
;
14 use rustc_ast
::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}
;
15 use rustc_ast
::{attr, Term}
;
16 use rustc_ast
::{GenericArg, MacArgs}
;
17 use rustc_ast
::{GenericBound, SelfKind, TraitBoundModifier}
;
18 use rustc_ast
::{InlineAsmOperand, InlineAsmRegOrRegClass}
;
19 use rustc_ast
::{InlineAsmOptions, InlineAsmTemplatePiece}
;
20 use rustc_span
::edition
::Edition
;
21 use rustc_span
::source_map
::{SourceMap, Spanned}
;
22 use rustc_span
::symbol
::{kw, sym, Ident, IdentPrinter, Symbol}
;
23 use rustc_span
::{BytePos, FileName, Span}
;
27 pub use self::delimited
::IterDelimited
;
29 pub enum MacHeader
<'a
> {
31 Keyword(&'
static str),
34 pub enum AnnNode
<'a
> {
37 Block(&'a ast
::Block
),
42 Crate(&'a ast
::Crate
),
46 fn pre(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
47 fn post(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
50 #[derive(Copy, Clone)]
53 impl PpAnn
for NoAnn {}
55 pub struct Comments
<'a
> {
57 comments
: Vec
<Comment
>,
61 impl<'a
> Comments
<'a
> {
62 pub fn new(sm
: &'a SourceMap
, filename
: FileName
, input
: String
) -> Comments
<'a
> {
63 let comments
= gather_comments(sm
, filename
, input
);
64 Comments { sm, comments, current: 0 }
67 pub fn next(&self) -> Option
<Comment
> {
68 self.comments
.get(self.current
).cloned()
71 pub fn trailing_comment(
73 span
: rustc_span
::Span
,
74 next_pos
: Option
<BytePos
>,
75 ) -> Option
<Comment
> {
76 if let Some(cmnt
) = self.next() {
77 if cmnt
.style
!= CommentStyle
::Trailing
{
80 let span_line
= self.sm
.lookup_char_pos(span
.hi());
81 let comment_line
= self.sm
.lookup_char_pos(cmnt
.pos
);
82 let next
= next_pos
.unwrap_or_else(|| cmnt
.pos
+ BytePos(1));
83 if span
.hi() < cmnt
.pos
&& cmnt
.pos
< next
&& span_line
.line
== comment_line
.line
{
92 pub struct State
<'a
> {
94 comments
: Option
<Comments
<'a
>>,
95 ann
: &'
a (dyn PpAnn
+ 'a
),
98 crate const INDENT_UNIT
: isize = 4;
100 /// Requires you to pass an input filename and reader so that
101 /// it can scan the input text for comments to copy forward.
102 pub fn print_crate
<'a
>(
112 State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann }
;
114 if is_expanded
&& !krate
.attrs
.iter().any(|attr
| attr
.has_name(sym
::no_core
)) {
115 // We need to print `#![no_std]` (and its feature gate) so that
116 // compiling pretty-printed source won't inject libstd again.
117 // However, we don't want these attributes in the AST because
118 // of the feature gate, so we fake them up here.
120 // `#![feature(prelude_import)]`
121 let pi_nested
= attr
::mk_nested_word_item(Ident
::with_dummy_span(sym
::prelude_import
));
122 let list
= attr
::mk_list_item(Ident
::with_dummy_span(sym
::feature
), vec
![pi_nested
]);
123 let fake_attr
= attr
::mk_attr_inner(list
);
124 s
.print_attribute(&fake_attr
);
126 // Currently, in Rust 2018 we don't have `extern crate std;` at the crate
127 // root, so this is not needed, and actually breaks things.
128 if edition
== Edition
::Edition2015
{
130 let no_std_meta
= attr
::mk_word_item(Ident
::with_dummy_span(sym
::no_std
));
131 let fake_attr
= attr
::mk_attr_inner(no_std_meta
);
132 s
.print_attribute(&fake_attr
);
136 s
.print_inner_attributes(&krate
.attrs
);
137 for item
in &krate
.items
{
140 s
.print_remaining_comments();
141 s
.ann
.post(&mut s
, AnnNode
::Crate(krate
));
145 /// This makes printed token streams look slightly nicer,
146 /// and also addresses some specific regressions described in #63896 and #73345.
147 fn tt_prepend_space(tt
: &TokenTree
, prev
: &TokenTree
) -> bool
{
148 if let TokenTree
::Token(token
) = prev
{
149 if matches
!(token
.kind
, token
::Dot
| token
::Dollar
) {
152 if let token
::DocComment(comment_kind
, ..) = token
.kind
{
153 return comment_kind
!= CommentKind
::Line
;
157 TokenTree
::Token(token
) => !matches
!(token
.kind
, token
::Comma
| token
::Not
| token
::Dot
),
158 TokenTree
::Delimited(_
, DelimToken
::Paren
, _
) => {
159 !matches
!(prev
, TokenTree
::Token(Token { kind: token::Ident(..), .. }
))
161 TokenTree
::Delimited(_
, DelimToken
::Bracket
, _
) => {
162 !matches
!(prev
, TokenTree
::Token(Token { kind: token::Pound, .. }
))
164 TokenTree
::Delimited(..) => true,
168 fn binop_to_string(op
: BinOpToken
) -> &'
static str {
174 token
::Percent
=> "%",
183 fn doc_comment_to_string(
184 comment_kind
: CommentKind
,
185 attr_style
: ast
::AttrStyle
,
188 match (comment_kind
, attr_style
) {
189 (CommentKind
::Line
, ast
::AttrStyle
::Outer
) => format
!("///{}", data
),
190 (CommentKind
::Line
, ast
::AttrStyle
::Inner
) => format
!("//!{}", data
),
191 (CommentKind
::Block
, ast
::AttrStyle
::Outer
) => format
!("/**{}*/", data
),
192 (CommentKind
::Block
, ast
::AttrStyle
::Inner
) => format
!("/*!{}*/", data
),
196 pub fn literal_to_string(lit
: token
::Lit
) -> String
{
197 let token
::Lit { kind, symbol, suffix }
= lit
;
198 let mut out
= match kind
{
199 token
::Byte
=> format
!("b'{}'", symbol
),
200 token
::Char
=> format
!("'{}'", symbol
),
201 token
::Str
=> format
!("\"{}\"", symbol
),
202 token
::StrRaw(n
) => {
203 format
!("r{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= symbol
)
205 token
::ByteStr
=> format
!("b\"{}\"", symbol
),
206 token
::ByteStrRaw(n
) => {
207 format
!("br{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= symbol
)
209 token
::Integer
| token
::Float
| token
::Bool
| token
::Err
=> symbol
.to_string(),
212 if let Some(suffix
) = suffix
{
213 out
.push_str(suffix
.as_str())
219 impl std
::ops
::Deref
for State
<'_
> {
220 type Target
= pp
::Printer
;
221 fn deref(&self) -> &Self::Target
{
226 impl std
::ops
::DerefMut
for State
<'_
> {
227 fn deref_mut(&mut self) -> &mut Self::Target
{
232 pub trait PrintState
<'a
>: std
::ops
::Deref
<Target
= pp
::Printer
> + std
::ops
::DerefMut
{
233 fn comments(&mut self) -> &mut Option
<Comments
<'a
>>;
234 fn print_ident(&mut self, ident
: Ident
);
235 fn print_generic_args(&mut self, args
: &ast
::GenericArgs
, colons_before_params
: bool
);
245 F
: FnMut(&mut Self, &T
),
248 if let Some((first
, rest
)) = elts
.split_first() {
254 self.word_space(sep
);
261 fn commasep
<T
, F
>(&mut self, b
: Breaks
, elts
: &[T
], op
: F
)
263 F
: FnMut(&mut Self, &T
),
265 self.strsep(",", false, b
, elts
, op
)
268 fn maybe_print_comment(&mut self, pos
: BytePos
) -> bool
{
269 let mut has_comment
= false;
270 while let Some(ref cmnt
) = self.next_comment() {
273 self.print_comment(cmnt
);
281 fn print_comment(&mut self, cmnt
: &Comment
) {
283 CommentStyle
::Mixed
=> {
284 if !self.is_beginning_of_line() {
287 if let Some((last
, lines
)) = cmnt
.lines
.split_last() {
291 self.word(line
.clone());
295 self.word(last
.clone());
302 CommentStyle
::Isolated
=> {
303 self.hardbreak_if_not_bol();
304 for line
in &cmnt
.lines
{
305 // Don't print empty lines because they will end up as trailing
307 if !line
.is_empty() {
308 self.word(line
.clone());
313 CommentStyle
::Trailing
=> {
314 if !self.is_beginning_of_line() {
317 if cmnt
.lines
.len() == 1 {
318 self.word(cmnt
.lines
[0].clone());
322 for line
in &cmnt
.lines
{
323 if !line
.is_empty() {
324 self.word(line
.clone());
331 CommentStyle
::BlankLine
=> {
332 // We need to do at least one, possibly two hardbreaks.
333 let twice
= match self.last_token() {
334 Some(pp
::Token
::String(s
)) => ";" == s
,
335 Some(pp
::Token
::Begin(_
)) => true,
336 Some(pp
::Token
::End
) => true,
345 if let Some(cmnts
) = self.comments() {
350 fn next_comment(&mut self) -> Option
<Comment
> {
351 self.comments().as_mut().and_then(|c
| c
.next())
354 fn maybe_print_trailing_comment(&mut self, span
: rustc_span
::Span
, next_pos
: Option
<BytePos
>) {
355 if let Some(cmnts
) = self.comments() {
356 if let Some(cmnt
) = cmnts
.trailing_comment(span
, next_pos
) {
357 self.print_comment(&cmnt
);
362 fn print_remaining_comments(&mut self) {
363 // If there aren't any remaining comments, then we need to manually
364 // make sure there is a line break at the end.
365 if self.next_comment().is_none() {
368 while let Some(ref cmnt
) = self.next_comment() {
369 self.print_comment(cmnt
)
373 fn print_literal(&mut self, lit
: &ast
::Lit
) {
374 self.maybe_print_comment(lit
.span
.lo());
375 self.word(lit
.token
.to_string())
378 fn print_string(&mut self, st
: &str, style
: ast
::StrStyle
) {
379 let st
= match style
{
380 ast
::StrStyle
::Cooked
=> (format
!("\"{}\"", st
.escape_debug())),
381 ast
::StrStyle
::Raw(n
) => {
382 format
!("r{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= st
)
388 fn print_symbol(&mut self, sym
: Symbol
, style
: ast
::StrStyle
) {
389 self.print_string(sym
.as_str(), style
);
392 fn print_inner_attributes(&mut self, attrs
: &[ast
::Attribute
]) -> bool
{
393 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, true)
396 fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs
: &[ast
::Attribute
]) -> bool
{
397 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, false)
400 fn print_outer_attributes(&mut self, attrs
: &[ast
::Attribute
]) -> bool
{
401 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, false, true)
404 fn print_inner_attributes_inline(&mut self, attrs
: &[ast
::Attribute
]) -> bool
{
405 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, true, true)
408 fn print_outer_attributes_inline(&mut self, attrs
: &[ast
::Attribute
]) -> bool
{
409 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, true, true)
412 fn print_either_attributes(
414 attrs
: &[ast
::Attribute
],
415 kind
: ast
::AttrStyle
,
417 trailing_hardbreak
: bool
,
419 let mut printed
= false;
421 if attr
.style
== kind
{
422 self.print_attribute_inline(attr
, is_inline
);
429 if printed
&& trailing_hardbreak
&& !is_inline
{
430 self.hardbreak_if_not_bol();
435 fn print_attribute(&mut self, attr
: &ast
::Attribute
) {
436 self.print_attribute_inline(attr
, false)
439 fn print_attribute_inline(&mut self, attr
: &ast
::Attribute
, is_inline
: bool
) {
441 self.hardbreak_if_not_bol();
443 self.maybe_print_comment(attr
.span
.lo());
445 ast
::AttrKind
::Normal(ref item
, _
) => {
447 ast
::AttrStyle
::Inner
=> self.word("#!["),
448 ast
::AttrStyle
::Outer
=> self.word("#["),
450 self.print_attr_item(&item
, attr
.span
);
453 ast
::AttrKind
::DocComment(comment_kind
, data
) => {
454 self.word(doc_comment_to_string(comment_kind
, attr
.style
, data
));
460 fn print_attr_item(&mut self, item
: &ast
::AttrItem
, span
: Span
) {
463 MacArgs
::Delimited(_
, delim
, tokens
) => self.print_mac_common(
464 Some(MacHeader
::Path(&item
.path
)),
472 MacArgs
::Empty
| MacArgs
::Eq(..) => {
473 self.print_path(&item
.path
, false, 0);
474 if let MacArgs
::Eq(_
, token
) = &item
.args
{
476 self.word_space("=");
477 let token_str
= self.token_to_string_ext(token
, true);
478 self.word(token_str
);
485 fn print_meta_list_item(&mut self, item
: &ast
::NestedMetaItem
) {
487 ast
::NestedMetaItem
::MetaItem(ref mi
) => self.print_meta_item(mi
),
488 ast
::NestedMetaItem
::Literal(ref lit
) => self.print_literal(lit
),
492 fn print_meta_item(&mut self, item
: &ast
::MetaItem
) {
493 self.ibox(INDENT_UNIT
);
495 ast
::MetaItemKind
::Word
=> self.print_path(&item
.path
, false, 0),
496 ast
::MetaItemKind
::NameValue(ref value
) => {
497 self.print_path(&item
.path
, false, 0);
499 self.word_space("=");
500 self.print_literal(value
);
502 ast
::MetaItemKind
::List(ref items
) => {
503 self.print_path(&item
.path
, false, 0);
505 self.commasep(Consistent
, &items
, |s
, i
| s
.print_meta_list_item(i
));
512 /// This doesn't deserve to be called "pretty" printing, but it should be
513 /// meaning-preserving. A quick hack that might help would be to look at the
514 /// spans embedded in the TTs to decide where to put spaces and newlines.
515 /// But it'd be better to parse these according to the grammar of the
516 /// appropriate macro, transcribe back into the grammar we just parsed from,
517 /// and then pretty-print the resulting AST nodes (so, e.g., we print
518 /// expression arguments as expressions). It can be done! I think.
519 fn print_tt(&mut self, tt
: &TokenTree
, convert_dollar_crate
: bool
) {
521 TokenTree
::Token(token
) => {
522 let token_str
= self.token_to_string_ext(&token
, convert_dollar_crate
);
523 self.word(token_str
);
524 if let token
::DocComment(..) = token
.kind
{
528 TokenTree
::Delimited(dspan
, delim
, tts
) => {
529 self.print_mac_common(
535 convert_dollar_crate
,
542 fn print_tts(&mut self, tts
: &TokenStream
, convert_dollar_crate
: bool
) {
543 let mut iter
= tts
.trees().peekable();
544 while let Some(tt
) = iter
.next() {
545 self.print_tt(&tt
, convert_dollar_crate
);
546 if let Some(next
) = iter
.peek() {
547 if tt_prepend_space(next
, &tt
) {
556 header
: Option
<MacHeader
<'_
>>,
558 ident
: Option
<Ident
>,
561 convert_dollar_crate
: bool
,
564 if delim
== DelimToken
::Brace
{
565 self.cbox(INDENT_UNIT
);
568 Some(MacHeader
::Path(path
)) => self.print_path(path
, false, 0),
569 Some(MacHeader
::Keyword(kw
)) => self.word(kw
),
575 if let Some(ident
) = ident
{
577 self.print_ident(ident
);
580 DelimToken
::Brace
=> {
581 if header
.is_some() || has_bang
|| ident
.is_some() {
590 let token_str
= self.token_kind_to_string(&token
::OpenDelim(delim
));
595 self.print_tts(tts
, convert_dollar_crate
);
598 DelimToken
::Brace
=> {
599 let empty
= tts
.is_empty();
600 self.bclose(span
, empty
);
603 let token_str
= self.token_kind_to_string(&token
::CloseDelim(delim
));
611 macro_def
: &ast
::MacroDef
,
614 print_visibility
: impl FnOnce(&mut Self),
616 let (kw
, has_bang
) = if macro_def
.macro_rules
{
617 ("macro_rules", true)
619 print_visibility(self);
622 self.print_mac_common(
623 Some(MacHeader
::Keyword(kw
)),
626 macro_def
.body
.delim(),
627 ¯o_def
.body
.inner_tokens(),
631 if macro_def
.body
.need_semicolon() {
636 fn print_path(&mut self, path
: &ast
::Path
, colons_before_params
: bool
, depth
: usize) {
637 self.maybe_print_comment(path
.span
.lo());
639 for (i
, segment
) in path
.segments
[..path
.segments
.len() - depth
].iter().enumerate() {
643 self.print_path_segment(segment
, colons_before_params
);
647 fn print_path_segment(&mut self, segment
: &ast
::PathSegment
, colons_before_params
: bool
) {
648 if segment
.ident
.name
!= kw
::PathRoot
{
649 self.print_ident(segment
.ident
);
650 if let Some(ref args
) = segment
.args
{
651 self.print_generic_args(args
, colons_before_params
);
656 fn head
<S
: Into
<Cow
<'
static, str>>>(&mut self, w
: S
) {
658 // Outer-box is consistent.
659 self.cbox(INDENT_UNIT
);
660 // Head-box is inconsistent.
662 // Keyword that starts the head.
668 fn bopen(&mut self) {
670 self.end(); // Close the head-box.
673 fn bclose_maybe_open(&mut self, span
: rustc_span
::Span
, empty
: bool
, close_box
: bool
) {
674 let has_comment
= self.maybe_print_comment(span
.hi());
675 if !empty
|| has_comment
{
676 self.break_offset_if_not_bol(1, -(INDENT_UNIT
as isize));
680 self.end(); // Close the outer-box.
684 fn bclose(&mut self, span
: rustc_span
::Span
, empty
: bool
) {
685 let close_box
= true;
686 self.bclose_maybe_open(span
, empty
, close_box
)
689 fn break_offset_if_not_bol(&mut self, n
: usize, off
: isize) {
690 if !self.is_beginning_of_line() {
691 self.break_offset(n
, off
)
693 if let Some(last_token
) = self.last_token_still_buffered() {
694 if last_token
.is_hardbreak_tok() {
695 // We do something pretty sketchy here: tuck the nonzero
696 // offset-adjustment we were going to deposit along with the
697 // break into the previous hardbreak.
698 self.replace_last_token_still_buffered(pp
::Printer
::hardbreak_tok_offset(off
));
704 fn nonterminal_to_string(&self, nt
: &Nonterminal
) -> String
{
706 token
::NtExpr(ref e
) => self.expr_to_string(e
),
707 token
::NtMeta(ref e
) => self.attr_item_to_string(e
),
708 token
::NtTy(ref e
) => self.ty_to_string(e
),
709 token
::NtPath(ref e
) => self.path_to_string(e
),
710 token
::NtItem(ref e
) => self.item_to_string(e
),
711 token
::NtBlock(ref e
) => self.block_to_string(e
),
712 token
::NtStmt(ref e
) => self.stmt_to_string(e
),
713 token
::NtPat(ref e
) => self.pat_to_string(e
),
714 token
::NtIdent(e
, is_raw
) => IdentPrinter
::for_ast_ident(e
, is_raw
).to_string(),
715 token
::NtLifetime(e
) => e
.to_string(),
716 token
::NtLiteral(ref e
) => self.expr_to_string(e
),
717 token
::NtVis(ref e
) => self.vis_to_string(e
),
721 /// Print the token kind precisely, without converting `$crate` into its respective crate name.
722 fn token_kind_to_string(&self, tok
: &TokenKind
) -> Cow
<'
static, str> {
723 self.token_kind_to_string_ext(tok
, None
)
726 fn token_kind_to_string_ext(
729 convert_dollar_crate
: Option
<Span
>,
730 ) -> Cow
<'
static, str> {
732 token
::Eq
=> "=".into(),
733 token
::Lt
=> "<".into(),
734 token
::Le
=> "<=".into(),
735 token
::EqEq
=> "==".into(),
736 token
::Ne
=> "!=".into(),
737 token
::Ge
=> ">=".into(),
738 token
::Gt
=> ">".into(),
739 token
::Not
=> "!".into(),
740 token
::Tilde
=> "~".into(),
741 token
::OrOr
=> "||".into(),
742 token
::AndAnd
=> "&&".into(),
743 token
::BinOp(op
) => binop_to_string(op
).into(),
744 token
::BinOpEq(op
) => format
!("{}=", binop_to_string(op
)).into(),
746 /* Structural symbols */
747 token
::At
=> "@".into(),
748 token
::Dot
=> ".".into(),
749 token
::DotDot
=> "..".into(),
750 token
::DotDotDot
=> "...".into(),
751 token
::DotDotEq
=> "..=".into(),
752 token
::Comma
=> ",".into(),
753 token
::Semi
=> ";".into(),
754 token
::Colon
=> ":".into(),
755 token
::ModSep
=> "::".into(),
756 token
::RArrow
=> "->".into(),
757 token
::LArrow
=> "<-".into(),
758 token
::FatArrow
=> "=>".into(),
759 token
::OpenDelim(token
::Paren
) => "(".into(),
760 token
::CloseDelim(token
::Paren
) => ")".into(),
761 token
::OpenDelim(token
::Bracket
) => "[".into(),
762 token
::CloseDelim(token
::Bracket
) => "]".into(),
763 token
::OpenDelim(token
::Brace
) => "{".into(),
764 token
::CloseDelim(token
::Brace
) => "}".into(),
765 token
::OpenDelim(token
::NoDelim
) | token
::CloseDelim(token
::NoDelim
) => "".into(),
766 token
::Pound
=> "#".into(),
767 token
::Dollar
=> "$".into(),
768 token
::Question
=> "?".into(),
769 token
::SingleQuote
=> "'".into(),
772 token
::Literal(lit
) => literal_to_string(lit
).into(),
774 /* Name components */
775 token
::Ident(s
, is_raw
) => {
776 IdentPrinter
::new(s
, is_raw
, convert_dollar_crate
).to_string().into()
778 token
::Lifetime(s
) => s
.to_string().into(),
781 token
::DocComment(comment_kind
, attr_style
, data
) => {
782 doc_comment_to_string(comment_kind
, attr_style
, data
).into()
784 token
::Eof
=> "<eof>".into(),
786 token
::Interpolated(ref nt
) => self.nonterminal_to_string(nt
).into(),
790 /// Print the token precisely, without converting `$crate` into its respective crate name.
791 fn token_to_string(&self, token
: &Token
) -> Cow
<'
static, str> {
792 self.token_to_string_ext(token
, false)
795 fn token_to_string_ext(&self, token
: &Token
, convert_dollar_crate
: bool
) -> Cow
<'
static, str> {
796 let convert_dollar_crate
= convert_dollar_crate
.then_some(token
.span
);
797 self.token_kind_to_string_ext(&token
.kind
, convert_dollar_crate
)
800 fn ty_to_string(&self, ty
: &ast
::Ty
) -> String
{
801 Self::to_string(|s
| s
.print_type(ty
))
804 fn bounds_to_string(&self, bounds
: &[ast
::GenericBound
]) -> String
{
805 Self::to_string(|s
| s
.print_type_bounds("", bounds
))
808 fn pat_to_string(&self, pat
: &ast
::Pat
) -> String
{
809 Self::to_string(|s
| s
.print_pat(pat
))
812 fn expr_to_string(&self, e
: &ast
::Expr
) -> String
{
813 Self::to_string(|s
| s
.print_expr(e
))
816 fn tt_to_string(&self, tt
: &TokenTree
) -> String
{
817 Self::to_string(|s
| s
.print_tt(tt
, false))
820 fn tts_to_string(&self, tokens
: &TokenStream
) -> String
{
821 Self::to_string(|s
| s
.print_tts(tokens
, false))
824 fn stmt_to_string(&self, stmt
: &ast
::Stmt
) -> String
{
825 Self::to_string(|s
| s
.print_stmt(stmt
))
828 fn item_to_string(&self, i
: &ast
::Item
) -> String
{
829 Self::to_string(|s
| s
.print_item(i
))
832 fn generic_params_to_string(&self, generic_params
: &[ast
::GenericParam
]) -> String
{
833 Self::to_string(|s
| s
.print_generic_params(generic_params
))
836 fn path_to_string(&self, p
: &ast
::Path
) -> String
{
837 Self::to_string(|s
| s
.print_path(p
, false, 0))
840 fn path_segment_to_string(&self, p
: &ast
::PathSegment
) -> String
{
841 Self::to_string(|s
| s
.print_path_segment(p
, false))
844 fn vis_to_string(&self, v
: &ast
::Visibility
) -> String
{
845 Self::to_string(|s
| s
.print_visibility(v
))
848 fn block_to_string(&self, blk
: &ast
::Block
) -> String
{
849 Self::to_string(|s
| {
850 // Containing cbox, will be closed by `print_block` at `}`.
852 // Head-ibox, will be closed by `print_block` after `{`.
858 fn meta_list_item_to_string(&self, li
: &ast
::NestedMetaItem
) -> String
{
859 Self::to_string(|s
| s
.print_meta_list_item(li
))
862 fn attr_item_to_string(&self, ai
: &ast
::AttrItem
) -> String
{
863 Self::to_string(|s
| s
.print_attr_item(ai
, ai
.path
.span
))
866 fn attribute_to_string(&self, attr
: &ast
::Attribute
) -> String
{
867 Self::to_string(|s
| s
.print_attribute(attr
))
870 fn param_to_string(&self, arg
: &ast
::Param
) -> String
{
871 Self::to_string(|s
| s
.print_param(arg
, false))
874 fn to_string(f
: impl FnOnce(&mut State
<'_
>)) -> String
{
875 let mut printer
= State
::new();
881 impl<'a
> PrintState
<'a
> for State
<'a
> {
882 fn comments(&mut self) -> &mut Option
<Comments
<'a
>> {
886 fn print_ident(&mut self, ident
: Ident
) {
887 self.word(IdentPrinter
::for_ast_ident(ident
, ident
.is_raw_guess()).to_string());
888 self.ann
.post(self, AnnNode
::Ident(&ident
))
891 fn print_generic_args(&mut self, args
: &ast
::GenericArgs
, colons_before_params
: bool
) {
892 if colons_before_params
{
897 ast
::GenericArgs
::AngleBracketed(ref data
) => {
899 self.commasep(Inconsistent
, &data
.args
, |s
, arg
| match arg
{
900 ast
::AngleBracketedArg
::Arg(a
) => s
.print_generic_arg(a
),
901 ast
::AngleBracketedArg
::Constraint(c
) => s
.print_assoc_constraint(c
),
906 ast
::GenericArgs
::Parenthesized(ref data
) => {
908 self.commasep(Inconsistent
, &data
.inputs
, |s
, ty
| s
.print_type(ty
));
910 self.print_fn_ret_ty(&data
.output
);
917 pub fn new() -> State
<'a
> {
918 State { s: pp::Printer::new(), comments: None, ann: &NoAnn }
921 crate fn commasep_cmnt
<T
, F
, G
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
, mut get_span
: G
)
923 F
: FnMut(&mut State
<'_
>, &T
),
924 G
: FnMut(&T
) -> rustc_span
::Span
,
927 let len
= elts
.len();
930 self.maybe_print_comment(get_span(elt
).hi());
935 self.maybe_print_trailing_comment(get_span(elt
), Some(get_span(&elts
[i
]).hi()));
936 self.space_if_not_bol();
942 crate fn commasep_exprs(&mut self, b
: Breaks
, exprs
: &[P
<ast
::Expr
>]) {
943 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(e
), |e
| e
.span
)
946 pub fn print_opt_lifetime(&mut self, lifetime
: &Option
<ast
::Lifetime
>) {
947 if let Some(lt
) = *lifetime
{
948 self.print_lifetime(lt
);
953 pub fn print_assoc_constraint(&mut self, constraint
: &ast
::AssocConstraint
) {
954 self.print_ident(constraint
.ident
);
955 constraint
.gen_args
.as_ref().map(|args
| self.print_generic_args(args
, false));
957 match &constraint
.kind
{
958 ast
::AssocConstraintKind
::Equality { term }
=> {
959 self.word_space("=");
961 Term
::Ty(ty
) => self.print_type(ty
),
962 Term
::Const(c
) => self.print_expr_anon_const(c
),
965 ast
::AssocConstraintKind
::Bound { bounds }
=> self.print_type_bounds(":", &*bounds
),
969 pub fn print_generic_arg(&mut self, generic_arg
: &GenericArg
) {
971 GenericArg
::Lifetime(lt
) => self.print_lifetime(*lt
),
972 GenericArg
::Type(ty
) => self.print_type(ty
),
973 GenericArg
::Const(ct
) => self.print_expr(&ct
.value
),
977 pub fn print_type(&mut self, ty
: &ast
::Ty
) {
978 self.maybe_print_comment(ty
.span
.lo());
981 ast
::TyKind
::Slice(ref ty
) => {
986 ast
::TyKind
::Ptr(ref mt
) => {
988 self.print_mt(mt
, true);
990 ast
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
992 self.print_opt_lifetime(lifetime
);
993 self.print_mt(mt
, false);
995 ast
::TyKind
::Never
=> {
998 ast
::TyKind
::Tup(ref elts
) => {
1000 self.commasep(Inconsistent
, &elts
, |s
, ty
| s
.print_type(ty
));
1001 if elts
.len() == 1 {
1006 ast
::TyKind
::Paren(ref typ
) => {
1008 self.print_type(typ
);
1011 ast
::TyKind
::BareFn(ref f
) => {
1012 self.print_ty_fn(f
.ext
, f
.unsafety
, &f
.decl
, None
, &f
.generic_params
);
1014 ast
::TyKind
::Path(None
, ref path
) => {
1015 self.print_path(path
, false, 0);
1017 ast
::TyKind
::Path(Some(ref qself
), ref path
) => self.print_qpath(path
, qself
, false),
1018 ast
::TyKind
::TraitObject(ref bounds
, syntax
) => {
1019 let prefix
= if syntax
== ast
::TraitObjectSyntax
::Dyn { "dyn" }
else { "" }
;
1020 self.print_type_bounds(prefix
, &bounds
);
1022 ast
::TyKind
::ImplTrait(_
, ref bounds
) => {
1023 self.print_type_bounds("impl", &bounds
);
1025 ast
::TyKind
::Array(ref ty
, ref length
) => {
1027 self.print_type(ty
);
1029 self.print_expr(&length
.value
);
1032 ast
::TyKind
::Typeof(ref e
) => {
1033 self.word("typeof(");
1034 self.print_expr(&e
.value
);
1037 ast
::TyKind
::Infer
=> {
1040 ast
::TyKind
::Err
=> {
1042 self.word("/*ERROR*/");
1045 ast
::TyKind
::ImplicitSelf
=> {
1048 ast
::TyKind
::MacCall(ref m
) => {
1051 ast
::TyKind
::CVarArgs
=> {
1058 fn print_trait_ref(&mut self, t
: &ast
::TraitRef
) {
1059 self.print_path(&t
.path
, false, 0)
1062 fn print_formal_generic_params(&mut self, generic_params
: &[ast
::GenericParam
]) {
1063 if !generic_params
.is_empty() {
1065 self.print_generic_params(generic_params
);
1070 fn print_poly_trait_ref(&mut self, t
: &ast
::PolyTraitRef
) {
1071 self.print_formal_generic_params(&t
.bound_generic_params
);
1072 self.print_trait_ref(&t
.trait_ref
)
1075 crate fn print_stmt(&mut self, st
: &ast
::Stmt
) {
1076 self.maybe_print_comment(st
.span
.lo());
1078 ast
::StmtKind
::Local(ref loc
) => {
1079 self.print_outer_attributes(&loc
.attrs
);
1080 self.space_if_not_bol();
1081 self.ibox(INDENT_UNIT
);
1082 self.word_nbsp("let");
1084 self.ibox(INDENT_UNIT
);
1085 self.print_local_decl(loc
);
1087 if let Some((init
, els
)) = loc
.kind
.init_else_opt() {
1089 self.word_space("=");
1090 self.print_expr(init
);
1091 if let Some(els
) = els
{
1092 self.cbox(INDENT_UNIT
);
1093 self.ibox(INDENT_UNIT
);
1094 self.word(" else ");
1095 self.print_block(els
);
1099 self.end(); // `let` ibox
1101 ast
::StmtKind
::Item(ref item
) => self.print_item(item
),
1102 ast
::StmtKind
::Expr(ref expr
) => {
1103 self.space_if_not_bol();
1104 self.print_expr_outer_attr_style(expr
, false);
1105 if classify
::expr_requires_semi_to_be_stmt(expr
) {
1109 ast
::StmtKind
::Semi(ref expr
) => {
1110 self.space_if_not_bol();
1111 self.print_expr_outer_attr_style(expr
, false);
1114 ast
::StmtKind
::Empty
=> {
1115 self.space_if_not_bol();
1118 ast
::StmtKind
::MacCall(ref mac
) => {
1119 self.space_if_not_bol();
1120 self.print_outer_attributes(&mac
.attrs
);
1121 self.print_mac(&mac
.mac
);
1122 if mac
.style
== ast
::MacStmtStyle
::Semicolon
{
1127 self.maybe_print_trailing_comment(st
.span
, None
)
1130 crate fn print_block(&mut self, blk
: &ast
::Block
) {
1131 self.print_block_with_attrs(blk
, &[])
1134 crate fn print_block_unclosed_indent(&mut self, blk
: &ast
::Block
) {
1135 self.print_block_maybe_unclosed(blk
, &[], false)
1138 crate fn print_block_with_attrs(&mut self, blk
: &ast
::Block
, attrs
: &[ast
::Attribute
]) {
1139 self.print_block_maybe_unclosed(blk
, attrs
, true)
1142 crate fn print_block_maybe_unclosed(
1145 attrs
: &[ast
::Attribute
],
1149 BlockCheckMode
::Unsafe(..) => self.word_space("unsafe"),
1150 BlockCheckMode
::Default
=> (),
1152 self.maybe_print_comment(blk
.span
.lo());
1153 self.ann
.pre(self, AnnNode
::Block(blk
));
1156 let has_attrs
= self.print_inner_attributes(attrs
);
1158 for (i
, st
) in blk
.stmts
.iter().enumerate() {
1160 ast
::StmtKind
::Expr(ref expr
) if i
== blk
.stmts
.len() - 1 => {
1161 self.maybe_print_comment(st
.span
.lo());
1162 self.space_if_not_bol();
1163 self.print_expr_outer_attr_style(expr
, false);
1164 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()));
1166 _
=> self.print_stmt(st
),
1170 let empty
= !has_attrs
&& blk
.stmts
.is_empty();
1171 self.bclose_maybe_open(blk
.span
, empty
, close_box
);
1172 self.ann
.post(self, AnnNode
::Block(blk
))
1175 /// Print a `let pat = expr` expression.
1176 crate fn print_let(&mut self, pat
: &ast
::Pat
, expr
: &ast
::Expr
) {
1178 self.print_pat(pat
);
1180 self.word_space("=");
1181 let npals
= || parser
::needs_par_as_let_scrutinee(expr
.precedence().order());
1182 self.print_expr_cond_paren(expr
, Self::cond_needs_par(expr
) || npals())
1185 crate fn print_mac(&mut self, m
: &ast
::MacCall
) {
1186 self.print_mac_common(
1187 Some(MacHeader
::Path(&m
.path
)),
1191 &m
.args
.inner_tokens(),
1197 fn print_inline_asm(&mut self, asm
: &ast
::InlineAsm
) {
1200 Operand(&'a InlineAsmOperand
),
1202 Options(InlineAsmOptions
),
1205 let mut args
= vec
![AsmArg
::Template(InlineAsmTemplatePiece
::to_string(&asm
.template
))];
1206 args
.extend(asm
.operands
.iter().map(|(o
, _
)| AsmArg
::Operand(o
)));
1207 for (abi
, _
) in &asm
.clobber_abis
{
1208 args
.push(AsmArg
::ClobberAbi(*abi
));
1210 if !asm
.options
.is_empty() {
1211 args
.push(AsmArg
::Options(asm
.options
));
1215 self.commasep(Consistent
, &args
, |s
, arg
| match arg
{
1216 AsmArg
::Template(template
) => s
.print_string(&template
, ast
::StrStyle
::Cooked
),
1217 AsmArg
::Operand(op
) => {
1218 let print_reg_or_class
= |s
: &mut Self, r
: &InlineAsmRegOrRegClass
| match r
{
1219 InlineAsmRegOrRegClass
::Reg(r
) => s
.print_symbol(*r
, ast
::StrStyle
::Cooked
),
1220 InlineAsmRegOrRegClass
::RegClass(r
) => s
.word(r
.to_string()),
1223 InlineAsmOperand
::In { reg, expr }
=> {
1226 print_reg_or_class(s
, reg
);
1231 InlineAsmOperand
::Out { reg, late, expr }
=> {
1232 s
.word(if *late { "lateout" }
else { "out" }
);
1234 print_reg_or_class(s
, reg
);
1238 Some(expr
) => s
.print_expr(expr
),
1239 None
=> s
.word("_"),
1242 InlineAsmOperand
::InOut { reg, late, expr }
=> {
1243 s
.word(if *late { "inlateout" }
else { "inout" }
);
1245 print_reg_or_class(s
, reg
);
1250 InlineAsmOperand
::SplitInOut { reg, late, in_expr, out_expr }
=> {
1251 s
.word(if *late { "inlateout" }
else { "inout" }
);
1253 print_reg_or_class(s
, reg
);
1256 s
.print_expr(in_expr
);
1260 Some(out_expr
) => s
.print_expr(out_expr
),
1261 None
=> s
.word("_"),
1264 InlineAsmOperand
::Const { anon_const }
=> {
1267 s
.print_expr(&anon_const
.value
);
1269 InlineAsmOperand
::Sym { expr }
=> {
1276 AsmArg
::ClobberAbi(abi
) => {
1277 s
.word("clobber_abi");
1279 s
.print_symbol(*abi
, ast
::StrStyle
::Cooked
);
1282 AsmArg
::Options(opts
) => {
1285 let mut options
= vec
![];
1286 if opts
.contains(InlineAsmOptions
::PURE
) {
1287 options
.push("pure");
1289 if opts
.contains(InlineAsmOptions
::NOMEM
) {
1290 options
.push("nomem");
1292 if opts
.contains(InlineAsmOptions
::READONLY
) {
1293 options
.push("readonly");
1295 if opts
.contains(InlineAsmOptions
::PRESERVES_FLAGS
) {
1296 options
.push("preserves_flags");
1298 if opts
.contains(InlineAsmOptions
::NORETURN
) {
1299 options
.push("noreturn");
1301 if opts
.contains(InlineAsmOptions
::NOSTACK
) {
1302 options
.push("nostack");
1304 if opts
.contains(InlineAsmOptions
::ATT_SYNTAX
) {
1305 options
.push("att_syntax");
1307 if opts
.contains(InlineAsmOptions
::RAW
) {
1308 options
.push("raw");
1310 if opts
.contains(InlineAsmOptions
::MAY_UNWIND
) {
1311 options
.push("may_unwind");
1313 s
.commasep(Inconsistent
, &options
, |s
, &opt
| {
1322 crate fn print_local_decl(&mut self, loc
: &ast
::Local
) {
1323 self.print_pat(&loc
.pat
);
1324 if let Some(ref ty
) = loc
.ty
{
1325 self.word_space(":");
1326 self.print_type(ty
);
1330 crate fn print_name(&mut self, name
: Symbol
) {
1331 self.word(name
.to_string());
1332 self.ann
.post(self, AnnNode
::Name(&name
))
1335 fn print_qpath(&mut self, path
: &ast
::Path
, qself
: &ast
::QSelf
, colons_before_params
: bool
) {
1337 self.print_type(&qself
.ty
);
1338 if qself
.position
> 0 {
1340 self.word_space("as");
1341 let depth
= path
.segments
.len() - qself
.position
;
1342 self.print_path(path
, false, depth
);
1345 for item_segment
in &path
.segments
[qself
.position
..] {
1347 self.print_ident(item_segment
.ident
);
1348 if let Some(ref args
) = item_segment
.args
{
1349 self.print_generic_args(args
, colons_before_params
)
1354 crate fn print_pat(&mut self, pat
: &ast
::Pat
) {
1355 self.maybe_print_comment(pat
.span
.lo());
1356 self.ann
.pre(self, AnnNode
::Pat(pat
));
1357 /* Pat isn't normalized, but the beauty of it
1358 is that it doesn't matter */
1360 PatKind
::Wild
=> self.word("_"),
1361 PatKind
::Ident(binding_mode
, ident
, ref sub
) => {
1362 match binding_mode
{
1363 ast
::BindingMode
::ByRef(mutbl
) => {
1364 self.word_nbsp("ref");
1365 self.print_mutability(mutbl
, false);
1367 ast
::BindingMode
::ByValue(ast
::Mutability
::Not
) => {}
1368 ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
) => {
1369 self.word_nbsp("mut");
1372 self.print_ident(ident
);
1373 if let Some(ref p
) = *sub
{
1375 self.word_space("@");
1379 PatKind
::TupleStruct(ref qself
, ref path
, ref elts
) => {
1380 if let Some(qself
) = qself
{
1381 self.print_qpath(path
, qself
, true);
1383 self.print_path(path
, true, 0);
1386 self.commasep(Inconsistent
, &elts
, |s
, p
| s
.print_pat(p
));
1389 PatKind
::Or(ref pats
) => {
1390 self.strsep("|", true, Inconsistent
, &pats
, |s
, p
| s
.print_pat(p
));
1392 PatKind
::Path(None
, ref path
) => {
1393 self.print_path(path
, true, 0);
1395 PatKind
::Path(Some(ref qself
), ref path
) => {
1396 self.print_qpath(path
, qself
, false);
1398 PatKind
::Struct(ref qself
, ref path
, ref fields
, etc
) => {
1399 if let Some(qself
) = qself
{
1400 self.print_qpath(path
, qself
, true);
1402 self.print_path(path
, true, 0);
1406 let empty
= fields
.is_empty() && !etc
;
1414 s
.cbox(INDENT_UNIT
);
1415 if !f
.is_shorthand
{
1416 s
.print_ident(f
.ident
);
1419 s
.print_pat(&f
.pat
);
1425 if !fields
.is_empty() {
1426 self.word_space(",");
1435 PatKind
::Tuple(ref elts
) => {
1437 self.commasep(Inconsistent
, &elts
, |s
, p
| s
.print_pat(p
));
1438 if elts
.len() == 1 {
1443 PatKind
::Box(ref inner
) => {
1445 self.print_pat(inner
);
1447 PatKind
::Ref(ref inner
, mutbl
) => {
1449 if mutbl
== ast
::Mutability
::Mut
{
1452 if let PatKind
::Ident(ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
), ..) =
1456 self.print_pat(inner
);
1459 self.print_pat(inner
);
1462 PatKind
::Lit(ref e
) => self.print_expr(&**e
),
1463 PatKind
::Range(ref begin
, ref end
, Spanned { node: ref end_kind, .. }
) => {
1464 if let Some(e
) = begin
{
1468 RangeEnd
::Included(RangeSyntax
::DotDotDot
) => self.word("..."),
1469 RangeEnd
::Included(RangeSyntax
::DotDotEq
) => self.word("..="),
1470 RangeEnd
::Excluded
=> self.word(".."),
1472 if let Some(e
) = end
{
1476 PatKind
::Slice(ref elts
) => {
1478 self.commasep(Inconsistent
, &elts
, |s
, p
| s
.print_pat(p
));
1481 PatKind
::Rest
=> self.word(".."),
1482 PatKind
::Paren(ref inner
) => {
1484 self.print_pat(inner
);
1487 PatKind
::MacCall(ref m
) => self.print_mac(m
),
1489 self.ann
.post(self, AnnNode
::Pat(pat
))
1492 fn print_explicit_self(&mut self, explicit_self
: &ast
::ExplicitSelf
) {
1493 match explicit_self
.node
{
1494 SelfKind
::Value(m
) => {
1495 self.print_mutability(m
, false);
1498 SelfKind
::Region(ref lt
, m
) => {
1500 self.print_opt_lifetime(lt
);
1501 self.print_mutability(m
, false);
1504 SelfKind
::Explicit(ref typ
, m
) => {
1505 self.print_mutability(m
, false);
1507 self.word_space(":");
1508 self.print_type(typ
)
1513 crate fn print_asyncness(&mut self, asyncness
: ast
::Async
) {
1514 if asyncness
.is_async() {
1515 self.word_nbsp("async");
1519 pub fn print_type_bounds(&mut self, prefix
: &'
static str, bounds
: &[ast
::GenericBound
]) {
1520 if !bounds
.is_empty() {
1522 let mut first
= true;
1523 for bound
in bounds
{
1524 if !(first
&& prefix
.is_empty()) {
1530 self.word_space("+");
1534 GenericBound
::Trait(tref
, modifier
) => {
1535 if modifier
== &TraitBoundModifier
::Maybe
{
1538 self.print_poly_trait_ref(tref
);
1540 GenericBound
::Outlives(lt
) => self.print_lifetime(*lt
),
1546 crate fn print_lifetime(&mut self, lifetime
: ast
::Lifetime
) {
1547 self.print_name(lifetime
.ident
.name
)
1550 crate fn print_lifetime_bounds(
1552 lifetime
: ast
::Lifetime
,
1553 bounds
: &ast
::GenericBounds
,
1555 self.print_lifetime(lifetime
);
1556 if !bounds
.is_empty() {
1558 for (i
, bound
) in bounds
.iter().enumerate() {
1563 ast
::GenericBound
::Outlives(lt
) => self.print_lifetime(*lt
),
1570 crate fn print_generic_params(&mut self, generic_params
: &[ast
::GenericParam
]) {
1571 if generic_params
.is_empty() {
1577 self.commasep(Inconsistent
, &generic_params
, |s
, param
| {
1578 s
.print_outer_attributes_inline(¶m
.attrs
);
1581 ast
::GenericParamKind
::Lifetime
=> {
1582 let lt
= ast
::Lifetime { id: param.id, ident: param.ident }
;
1583 s
.print_lifetime_bounds(lt
, ¶m
.bounds
)
1585 ast
::GenericParamKind
::Type { ref default }
=> {
1586 s
.print_ident(param
.ident
);
1587 s
.print_type_bounds(":", ¶m
.bounds
);
1588 if let Some(ref default) = default {
1591 s
.print_type(default)
1594 ast
::GenericParamKind
::Const { ref ty, kw_span: _, ref default }
=> {
1595 s
.word_space("const");
1596 s
.print_ident(param
.ident
);
1600 s
.print_type_bounds(":", ¶m
.bounds
);
1601 if let Some(ref default) = default {
1604 s
.print_expr(&default.value
);
1613 pub fn print_mutability(&mut self, mutbl
: ast
::Mutability
, print_const
: bool
) {
1615 ast
::Mutability
::Mut
=> self.word_nbsp("mut"),
1616 ast
::Mutability
::Not
=> {
1618 self.word_nbsp("const");
1624 crate fn print_mt(&mut self, mt
: &ast
::MutTy
, print_const
: bool
) {
1625 self.print_mutability(mt
.mutbl
, print_const
);
1626 self.print_type(&mt
.ty
)
1629 crate fn print_param(&mut self, input
: &ast
::Param
, is_closure
: bool
) {
1630 self.ibox(INDENT_UNIT
);
1632 self.print_outer_attributes_inline(&input
.attrs
);
1634 match input
.ty
.kind
{
1635 ast
::TyKind
::Infer
if is_closure
=> self.print_pat(&input
.pat
),
1637 if let Some(eself
) = input
.to_self() {
1638 self.print_explicit_self(&eself
);
1640 let invalid
= if let PatKind
::Ident(_
, ident
, _
) = input
.pat
.kind
{
1641 ident
.name
== kw
::Empty
1646 self.print_pat(&input
.pat
);
1650 self.print_type(&input
.ty
);
1657 crate fn print_fn_ret_ty(&mut self, fn_ret_ty
: &ast
::FnRetTy
) {
1658 if let ast
::FnRetTy
::Ty(ty
) = fn_ret_ty
{
1659 self.space_if_not_bol();
1660 self.ibox(INDENT_UNIT
);
1661 self.word_space("->");
1662 self.print_type(ty
);
1664 self.maybe_print_comment(ty
.span
.lo());
1668 crate fn print_ty_fn(
1671 unsafety
: ast
::Unsafe
,
1673 name
: Option
<Ident
>,
1674 generic_params
: &[ast
::GenericParam
],
1676 self.ibox(INDENT_UNIT
);
1677 self.print_formal_generic_params(generic_params
);
1678 let generics
= ast
::Generics
{
1680 where_clause
: ast
::WhereClause
{
1681 has_where_token
: false,
1682 predicates
: Vec
::new(),
1683 span
: rustc_span
::DUMMY_SP
,
1685 span
: rustc_span
::DUMMY_SP
,
1687 let header
= ast
::FnHeader { unsafety, ext, ..ast::FnHeader::default() }
;
1688 self.print_fn(decl
, header
, name
, &generics
);
1692 crate fn print_fn_header_info(&mut self, header
: ast
::FnHeader
) {
1693 self.print_constness(header
.constness
);
1694 self.print_asyncness(header
.asyncness
);
1695 self.print_unsafety(header
.unsafety
);
1698 ast
::Extern
::None
=> {}
1699 ast
::Extern
::Implicit
=> {
1700 self.word_nbsp("extern");
1702 ast
::Extern
::Explicit(abi
) => {
1703 self.word_nbsp("extern");
1704 self.print_literal(&abi
.as_lit());
1712 crate fn print_unsafety(&mut self, s
: ast
::Unsafe
) {
1714 ast
::Unsafe
::No
=> {}
1715 ast
::Unsafe
::Yes(_
) => self.word_nbsp("unsafe"),
1719 crate fn print_constness(&mut self, s
: ast
::Const
) {
1721 ast
::Const
::No
=> {}
1722 ast
::Const
::Yes(_
) => self.word_nbsp("const"),
1726 crate fn print_is_auto(&mut self, s
: ast
::IsAuto
) {
1728 ast
::IsAuto
::Yes
=> self.word_nbsp("auto"),
1729 ast
::IsAuto
::No
=> {}