]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_ast_pretty/src/pprust/state.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / compiler / rustc_ast_pretty / src / pprust / state.rs
CommitLineData
5099ac24
FG
1mod delimited;
2mod expr;
3mod item;
4
74b04a01
XL
5use crate::pp::Breaks::{Consistent, Inconsistent};
6use crate::pp::{self, Breaks};
7
74b04a01 8use rustc_ast::ptr::P;
04454e1e 9use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
f035d41b 10use rustc_ast::tokenstream::{TokenStream, TokenTree};
3dfed10e
XL
11use rustc_ast::util::classify;
12use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
5099ac24 13use rustc_ast::util::parser;
f2b60f7d
FG
14use rustc_ast::{self as ast, BlockCheckMode, Mutability, PatKind, RangeEnd, RangeSyntax};
15use rustc_ast::{attr, BindingAnnotation, ByRef, Term};
04454e1e 16use rustc_ast::{GenericArg, MacArgs, MacArgsEq};
3dfed10e
XL
17use rustc_ast::{GenericBound, SelfKind, TraitBoundModifier};
18use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
19use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
74b04a01
XL
20use rustc_span::edition::Edition;
21use rustc_span::source_map::{SourceMap, Spanned};
f9f354fc 22use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
dfeec247 23use rustc_span::{BytePos, FileName, Span};
1a4d82fc 24
f2b60f7d 25use rustc_ast::attr::AttrIdGenerator;
a1dfa0c6 26use std::borrow::Cow;
416331ca 27
5099ac24
FG
28pub use self::delimited::IterDelimited;
29
416331ca
XL
30pub enum MacHeader<'a> {
31 Path(&'a ast::Path),
32 Keyword(&'static str),
33}
1a4d82fc
JJ
34
35pub enum AnnNode<'a> {
f9f354fc
XL
36 Ident(&'a Ident),
37 Name(&'a Symbol),
b7449926
XL
38 Block(&'a ast::Block),
39 Item(&'a ast::Item),
40 SubItem(ast::NodeId),
41 Expr(&'a ast::Expr),
42 Pat(&'a ast::Pat),
e1599b0c 43 Crate(&'a ast::Crate),
223e47cc
LB
44}
45
1a4d82fc 46pub trait PpAnn {
dfeec247
XL
47 fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
48 fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
223e47cc
LB
49}
50
c34b1796 51#[derive(Copy, Clone)]
1a4d82fc
JJ
52pub struct NoAnn;
53
54impl PpAnn for NoAnn {}
55
416331ca 56pub struct Comments<'a> {
74b04a01 57 sm: &'a SourceMap,
3dfed10e 58 comments: Vec<Comment>,
416331ca 59 current: usize,
223e47cc
LB
60}
61
416331ca 62impl<'a> Comments<'a> {
74b04a01 63 pub fn new(sm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> {
3dfed10e 64 let comments = gather_comments(sm, filename, input);
74b04a01 65 Comments { sm, comments, current: 0 }
416331ca
XL
66 }
67
3dfed10e 68 pub fn next(&self) -> Option<Comment> {
416331ca
XL
69 self.comments.get(self.current).cloned()
70 }
71
72 pub fn trailing_comment(
29967ef6 73 &self,
dfeec247 74 span: rustc_span::Span,
416331ca 75 next_pos: Option<BytePos>,
3dfed10e 76 ) -> Option<Comment> {
416331ca 77 if let Some(cmnt) = self.next() {
3dfed10e 78 if cmnt.style != CommentStyle::Trailing {
dfeec247
XL
79 return None;
80 }
74b04a01
XL
81 let span_line = self.sm.lookup_char_pos(span.hi());
82 let comment_line = self.sm.lookup_char_pos(cmnt.pos);
416331ca
XL
83 let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1));
84 if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line {
85 return Some(cmnt);
86 }
87 }
88
89 None
1a4d82fc
JJ
90 }
91}
92
416331ca
XL
93pub struct State<'a> {
94 pub s: pp::Printer,
95 comments: Option<Comments<'a>>,
dfeec247 96 ann: &'a (dyn PpAnn + 'a),
416331ca 97}
1a4d82fc 98
923072b8 99pub(crate) const INDENT_UNIT: isize = 4;
1a4d82fc
JJ
100
101/// Requires you to pass an input filename and reader so that
48663c56 102/// it can scan the input text for comments to copy forward.
dfeec247 103pub fn print_crate<'a>(
74b04a01 104 sm: &'a SourceMap,
dfeec247
XL
105 krate: &ast::Crate,
106 filename: FileName,
107 input: String,
108 ann: &'a dyn PpAnn,
109 is_expanded: bool,
74b04a01 110 edition: Edition,
f2b60f7d 111 g: &AttrIdGenerator,
dfeec247 112) -> String {
6a06907d 113 let mut s =
5099ac24 114 State { s: pp::Printer::new(), comments: Some(Comments::new(sm, filename, input)), ann };
32a655c1 115
fc512014 116 if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
85aaf69f
SL
117 // We need to print `#![no_std]` (and its feature gate) so that
118 // compiling pretty-printed source won't inject libstd again.
e1599b0c 119 // However, we don't want these attributes in the AST because
85aaf69f
SL
120 // of the feature gate, so we fake them up here.
121
e1599b0c 122 // `#![feature(prelude_import)]`
f9f354fc
XL
123 let pi_nested = attr::mk_nested_word_item(Ident::with_dummy_span(sym::prelude_import));
124 let list = attr::mk_list_item(Ident::with_dummy_span(sym::feature), vec![pi_nested]);
f2b60f7d 125 let fake_attr = attr::mk_attr_inner(g, list);
416331ca 126 s.print_attribute(&fake_attr);
85aaf69f 127
e1599b0c
XL
128 // Currently, in Rust 2018 we don't have `extern crate std;` at the crate
129 // root, so this is not needed, and actually breaks things.
74b04a01 130 if edition == Edition::Edition2015 {
e1599b0c 131 // `#![no_std]`
f9f354fc 132 let no_std_meta = attr::mk_word_item(Ident::with_dummy_span(sym::no_std));
f2b60f7d 133 let fake_attr = attr::mk_attr_inner(g, no_std_meta);
e1599b0c
XL
134 s.print_attribute(&fake_attr);
135 }
85aaf69f
SL
136 }
137
6a06907d
XL
138 s.print_inner_attributes(&krate.attrs);
139 for item in &krate.items {
140 s.print_item(item);
141 }
416331ca 142 s.print_remaining_comments();
e1599b0c 143 s.ann.post(&mut s, AnnNode::Crate(krate));
041b39d2 144 s.s.eof()
1a4d82fc
JJ
145}
146
136023e0
XL
147/// This makes printed token streams look slightly nicer,
148/// and also addresses some specific regressions described in #63896 and #73345.
ba9703b0 149fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
064997fb 150 if let TokenTree::Token(token, _) = prev {
136023e0 151 if matches!(token.kind, token::Dot | token::Dollar) {
17df50a5
XL
152 return false;
153 }
3dfed10e
XL
154 if let token::DocComment(comment_kind, ..) = token.kind {
155 return comment_kind != CommentKind::Line;
f035d41b
XL
156 }
157 }
416331ca 158 match tt {
064997fb 159 TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
04454e1e 160 TokenTree::Delimited(_, Delimiter::Parenthesis, _) => {
064997fb 161 !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _))
29967ef6 162 }
04454e1e 163 TokenTree::Delimited(_, Delimiter::Bracket, _) => {
064997fb 164 !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _))
29967ef6 165 }
f035d41b 166 TokenTree::Delimited(..) => true,
d9579d0f 167 }
1a4d82fc
JJ
168}
169
041b39d2 170fn binop_to_string(op: BinOpToken) -> &'static str {
1a4d82fc 171 match op {
dfeec247
XL
172 token::Plus => "+",
173 token::Minus => "-",
174 token::Star => "*",
175 token::Slash => "/",
176 token::Percent => "%",
177 token::Caret => "^",
178 token::And => "&",
179 token::Or => "|",
180 token::Shl => "<<",
181 token::Shr => ">>",
1a4d82fc
JJ
182 }
183}
184
3dfed10e
XL
185fn doc_comment_to_string(
186 comment_kind: CommentKind,
187 attr_style: ast::AttrStyle,
188 data: Symbol,
189) -> String {
190 match (comment_kind, attr_style) {
191 (CommentKind::Line, ast::AttrStyle::Outer) => format!("///{}", data),
192 (CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{}", data),
193 (CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{}*/", data),
194 (CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{}*/", data),
195 }
196}
197
dc9dc135
XL
198pub fn literal_to_string(lit: token::Lit) -> String {
199 let token::Lit { kind, symbol, suffix } = lit;
200 let mut out = match kind {
dfeec247
XL
201 token::Byte => format!("b'{}'", symbol),
202 token::Char => format!("'{}'", symbol),
203 token::Str => format!("\"{}\"", symbol),
204 token::StrRaw(n) => {
205 format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
206 }
207 token::ByteStr => format!("b\"{}\"", symbol),
208 token::ByteStrRaw(n) => {
209 format!("br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol)
210 }
211 token::Integer | token::Float | token::Bool | token::Err => symbol.to_string(),
48663c56
XL
212 };
213
214 if let Some(suffix) = suffix {
a2a8927a 215 out.push_str(suffix.as_str())
48663c56
XL
216 }
217
218 out
219}
220
416331ca
XL
221impl std::ops::Deref for State<'_> {
222 type Target = pp::Printer;
223 fn deref(&self) -> &Self::Target {
224 &self.s
1a4d82fc 225 }
416331ca 226}
223e47cc 227
416331ca
XL
228impl std::ops::DerefMut for State<'_> {
229 fn deref_mut(&mut self) -> &mut Self::Target {
230 &mut self.s
b039eaaf 231 }
416331ca 232}
223e47cc 233
e1599b0c 234pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
416331ca 235 fn comments(&mut self) -> &mut Option<Comments<'a>>;
f9f354fc 236 fn print_ident(&mut self, ident: Ident);
416331ca 237 fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
223e47cc 238
dfeec247
XL
239 fn strsep<T, F>(
240 &mut self,
241 sep: &'static str,
242 space_before: bool,
243 b: Breaks,
244 elts: &[T],
245 mut op: F,
246 ) where
247 F: FnMut(&mut Self, &T),
b039eaaf 248 {
416331ca 249 self.rbox(0, b);
e1599b0c
XL
250 if let Some((first, rest)) = elts.split_first() {
251 op(self, first);
252 for elt in rest {
253 if space_before {
254 self.space();
255 }
256 self.word_space(sep);
257 op(self, elt);
258 }
b039eaaf 259 }
416331ca 260 self.end();
b039eaaf
SL
261 }
262
e1599b0c 263 fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], op: F)
dfeec247
XL
264 where
265 F: FnMut(&mut Self, &T),
e1599b0c
XL
266 {
267 self.strsep(",", false, b, elts, op)
268 }
269
a2a8927a
XL
270 fn maybe_print_comment(&mut self, pos: BytePos) -> bool {
271 let mut has_comment = false;
c30ab7b3
SL
272 while let Some(ref cmnt) = self.next_comment() {
273 if cmnt.pos < pos {
a2a8927a 274 has_comment = true;
416331ca 275 self.print_comment(cmnt);
c30ab7b3 276 } else {
dfeec247 277 break;
b039eaaf
SL
278 }
279 }
a2a8927a 280 has_comment
b039eaaf
SL
281 }
282
3dfed10e 283 fn print_comment(&mut self, cmnt: &Comment) {
416331ca 284 match cmnt.style {
3dfed10e
XL
285 CommentStyle::Mixed => {
286 if !self.is_beginning_of_line() {
287 self.zerobreak();
288 }
289 if let Some((last, lines)) = cmnt.lines.split_last() {
290 self.ibox(0);
291
292 for line in lines {
293 self.word(line.clone());
294 self.hardbreak()
295 }
296
297 self.word(last.clone());
298 self.space();
299
300 self.end();
301 }
416331ca 302 self.zerobreak()
b039eaaf 303 }
3dfed10e 304 CommentStyle::Isolated => {
416331ca 305 self.hardbreak_if_not_bol();
b039eaaf
SL
306 for line in &cmnt.lines {
307 // Don't print empty lines because they will end up as trailing
e1599b0c 308 // whitespace.
b039eaaf 309 if !line.is_empty() {
416331ca 310 self.word(line.clone());
b039eaaf 311 }
416331ca 312 self.hardbreak();
b039eaaf 313 }
b039eaaf 314 }
3dfed10e 315 CommentStyle::Trailing => {
416331ca
XL
316 if !self.is_beginning_of_line() {
317 self.word(" ");
c30ab7b3 318 }
b039eaaf 319 if cmnt.lines.len() == 1 {
416331ca
XL
320 self.word(cmnt.lines[0].clone());
321 self.hardbreak()
b039eaaf 322 } else {
5099ac24 323 self.visual_align();
b039eaaf
SL
324 for line in &cmnt.lines {
325 if !line.is_empty() {
416331ca 326 self.word(line.clone());
b039eaaf 327 }
416331ca 328 self.hardbreak();
b039eaaf 329 }
416331ca 330 self.end();
b039eaaf
SL
331 }
332 }
3dfed10e 333 CommentStyle::BlankLine => {
b039eaaf 334 // We need to do at least one, possibly two hardbreaks.
416331ca 335 let twice = match self.last_token() {
5099ac24
FG
336 Some(pp::Token::String(s)) => ";" == s,
337 Some(pp::Token::Begin(_)) => true,
338 Some(pp::Token::End) => true,
dfeec247 339 _ => false,
b039eaaf 340 };
416331ca
XL
341 if twice {
342 self.hardbreak();
b039eaaf 343 }
416331ca 344 self.hardbreak();
b039eaaf 345 }
416331ca 346 }
74b04a01
XL
347 if let Some(cmnts) = self.comments() {
348 cmnts.current += 1;
b039eaaf
SL
349 }
350 }
351
3dfed10e 352 fn next_comment(&mut self) -> Option<Comment> {
416331ca 353 self.comments().as_mut().and_then(|c| c.next())
b039eaaf
SL
354 }
355
a2a8927a
XL
356 fn maybe_print_trailing_comment(&mut self, span: rustc_span::Span, next_pos: Option<BytePos>) {
357 if let Some(cmnts) = self.comments() {
358 if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) {
359 self.print_comment(&cmnt);
360 }
361 }
362 }
363
364 fn print_remaining_comments(&mut self) {
365 // If there aren't any remaining comments, then we need to manually
366 // make sure there is a line break at the end.
367 if self.next_comment().is_none() {
368 self.hardbreak();
369 }
370 while let Some(ref cmnt) = self.next_comment() {
371 self.print_comment(cmnt)
372 }
373 }
374
416331ca
XL
375 fn print_literal(&mut self, lit: &ast::Lit) {
376 self.maybe_print_comment(lit.span.lo());
f2b60f7d 377 self.word(lit.token_lit.to_string())
b039eaaf
SL
378 }
379
dfeec247 380 fn print_string(&mut self, st: &str, style: ast::StrStyle) {
b039eaaf 381 let st = match style {
064997fb 382 ast::StrStyle::Cooked => format!("\"{}\"", st.escape_debug()),
7453a54e 383 ast::StrStyle::Raw(n) => {
dfeec247 384 format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = st)
b039eaaf
SL
385 }
386 };
416331ca 387 self.word(st)
b039eaaf
SL
388 }
389
3dfed10e 390 fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) {
a2a8927a 391 self.print_string(sym.as_str(), style);
3dfed10e
XL
392 }
393
a2a8927a 394 fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool {
92a42be0
SL
395 self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
396 }
397
a2a8927a 398 fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool {
92a42be0 399 self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
b039eaaf
SL
400 }
401
a2a8927a 402 fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool {
92a42be0
SL
403 self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
404 }
405
a2a8927a 406 fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
92a42be0
SL
407 self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true)
408 }
409
a2a8927a 410 fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool {
92a42be0
SL
411 self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
412 }
413
dfeec247
XL
414 fn print_either_attributes(
415 &mut self,
416 attrs: &[ast::Attribute],
417 kind: ast::AttrStyle,
418 is_inline: bool,
419 trailing_hardbreak: bool,
a2a8927a
XL
420 ) -> bool {
421 let mut printed = false;
b039eaaf 422 for attr in attrs {
476ff2be 423 if attr.style == kind {
416331ca 424 self.print_attribute_inline(attr, is_inline);
3157f602 425 if is_inline {
416331ca 426 self.nbsp();
3157f602 427 }
a2a8927a 428 printed = true;
b039eaaf
SL
429 }
430 }
a2a8927a 431 if printed && trailing_hardbreak && !is_inline {
416331ca 432 self.hardbreak_if_not_bol();
83c7162d 433 }
a2a8927a 434 printed
83c7162d
XL
435 }
436
416331ca 437 fn print_attribute(&mut self, attr: &ast::Attribute) {
92a42be0
SL
438 self.print_attribute_inline(attr, false)
439 }
440
dfeec247 441 fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) {
92a42be0 442 if !is_inline {
416331ca 443 self.hardbreak_if_not_bol();
92a42be0 444 }
416331ca 445 self.maybe_print_comment(attr.span.lo());
60c5eb7d 446 match attr.kind {
f2b60f7d 447 ast::AttrKind::Normal(ref normal) => {
60c5eb7d
XL
448 match attr.style {
449 ast::AttrStyle::Inner => self.word("#!["),
450 ast::AttrStyle::Outer => self.word("#["),
451 }
f2b60f7d 452 self.print_attr_item(&normal.item, attr.span);
60c5eb7d
XL
453 self.word("]");
454 }
3dfed10e
XL
455 ast::AttrKind::DocComment(comment_kind, data) => {
456 self.word(doc_comment_to_string(comment_kind, attr.style, data));
60c5eb7d 457 self.hardbreak()
416331ca 458 }
e74abb32
XL
459 }
460 }
461
462 fn print_attr_item(&mut self, item: &ast::AttrItem, span: Span) {
463 self.ibox(0);
60c5eb7d
XL
464 match &item.args {
465 MacArgs::Delimited(_, delim, tokens) => self.print_mac_common(
466 Some(MacHeader::Path(&item.path)),
467 false,
468 None,
04454e1e 469 Some(delim.to_token()),
f035d41b 470 tokens,
60c5eb7d
XL
471 true,
472 span,
473 ),
04454e1e 474 MacArgs::Empty => {
e74abb32 475 self.print_path(&item.path, false, 0);
04454e1e
FG
476 }
477 MacArgs::Eq(_, MacArgsEq::Ast(expr)) => {
478 self.print_path(&item.path, false, 0);
479 self.space();
480 self.word_space("=");
481 let token_str = self.expr_to_string(expr);
482 self.word(token_str);
483 }
484 MacArgs::Eq(_, MacArgsEq::Hir(lit)) => {
485 self.print_path(&item.path, false, 0);
486 self.space();
487 self.word_space("=");
488 let token_str = self.literal_to_string(lit);
489 self.word(token_str);
cc61c64b 490 }
b039eaaf 491 }
e74abb32 492 self.end();
b039eaaf 493 }
1a4d82fc 494
416331ca 495 fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {
532ac7d7 496 match item {
dfeec247
XL
497 ast::NestedMetaItem::MetaItem(ref mi) => self.print_meta_item(mi),
498 ast::NestedMetaItem::Literal(ref lit) => self.print_literal(lit),
9e0c209e
SL
499 }
500 }
501
416331ca
XL
502 fn print_meta_item(&mut self, item: &ast::MetaItem) {
503 self.ibox(INDENT_UNIT);
e74abb32 504 match item.kind {
416331ca 505 ast::MetaItemKind::Word => self.print_path(&item.path, false, 0),
476ff2be 506 ast::MetaItemKind::NameValue(ref value) => {
416331ca
XL
507 self.print_path(&item.path, false, 0);
508 self.space();
509 self.word_space("=");
510 self.print_literal(value);
b039eaaf 511 }
476ff2be 512 ast::MetaItemKind::List(ref items) => {
416331ca
XL
513 self.print_path(&item.path, false, 0);
514 self.popen();
a2a8927a 515 self.commasep(Consistent, &items, |s, i| s.print_meta_list_item(i));
416331ca 516 self.pclose();
b039eaaf
SL
517 }
518 }
416331ca 519 self.end();
b039eaaf 520 }
92a42be0 521
cc61c64b
XL
522 /// This doesn't deserve to be called "pretty" printing, but it should be
523 /// meaning-preserving. A quick hack that might help would be to look at the
524 /// spans embedded in the TTs to decide where to put spaces and newlines.
525 /// But it'd be better to parse these according to the grammar of the
526 /// appropriate macro, transcribe back into the grammar we just parsed from,
527 /// and then pretty-print the resulting AST nodes (so, e.g., we print
528 /// expression arguments as expressions). It can be done! I think.
f035d41b 529 fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) {
cc61c64b 530 match tt {
064997fb 531 TokenTree::Token(token, _) => {
29967ef6
XL
532 let token_str = self.token_to_string_ext(&token, convert_dollar_crate);
533 self.word(token_str);
ba9703b0
XL
534 if let token::DocComment(..) = token.kind {
535 self.hardbreak()
cc61c64b
XL
536 }
537 }
416331ca
XL
538 TokenTree::Delimited(dspan, delim, tts) => {
539 self.print_mac_common(
dfeec247
XL
540 None,
541 false,
542 None,
04454e1e 543 Some(*delim),
dfeec247
XL
544 tts,
545 convert_dollar_crate,
546 dspan.entire(),
416331ca
XL
547 );
548 }
cc61c64b
XL
549 }
550 }
551
f035d41b
XL
552 fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) {
553 let mut iter = tts.trees().peekable();
ba9703b0 554 while let Some(tt) = iter.next() {
923072b8 555 self.print_tt(tt, convert_dollar_crate);
f035d41b 556 if let Some(next) = iter.peek() {
923072b8 557 if tt_prepend_space(next, tt) {
f035d41b
XL
558 self.space();
559 }
cc61c64b 560 }
cc61c64b 561 }
cc61c64b
XL
562 }
563
416331ca
XL
564 fn print_mac_common(
565 &mut self,
566 header: Option<MacHeader<'_>>,
567 has_bang: bool,
f9f354fc 568 ident: Option<Ident>,
04454e1e 569 delim: Option<Delimiter>,
f035d41b 570 tts: &TokenStream,
416331ca
XL
571 convert_dollar_crate: bool,
572 span: Span,
573 ) {
04454e1e 574 if delim == Some(Delimiter::Brace) {
416331ca
XL
575 self.cbox(INDENT_UNIT);
576 }
577 match header {
578 Some(MacHeader::Path(path)) => self.print_path(path, false, 0),
579 Some(MacHeader::Keyword(kw)) => self.word(kw),
580 None => {}
581 }
582 if has_bang {
583 self.word("!");
584 }
585 if let Some(ident) = ident {
586 self.nbsp();
587 self.print_ident(ident);
588 }
589 match delim {
04454e1e 590 Some(Delimiter::Brace) => {
416331ca
XL
591 if header.is_some() || has_bang || ident.is_some() {
592 self.nbsp();
593 }
594 self.word("{");
595 if !tts.is_empty() {
596 self.space();
597 }
04454e1e
FG
598 self.ibox(0);
599 self.print_tts(tts, convert_dollar_crate);
600 self.end();
a2a8927a
XL
601 let empty = tts.is_empty();
602 self.bclose(span, empty);
603 }
04454e1e
FG
604 Some(delim) => {
605 let token_str = self.token_kind_to_string(&token::OpenDelim(delim));
606 self.word(token_str);
607 self.ibox(0);
608 self.print_tts(tts, convert_dollar_crate);
609 self.end();
29967ef6 610 let token_str = self.token_kind_to_string(&token::CloseDelim(delim));
04454e1e
FG
611 self.word(token_str);
612 }
613 None => {
614 self.ibox(0);
615 self.print_tts(tts, convert_dollar_crate);
616 self.end();
29967ef6 617 }
ff7c6d11 618 }
b039eaaf
SL
619 }
620
94222f64
XL
621 fn print_mac_def(
622 &mut self,
623 macro_def: &ast::MacroDef,
624 ident: &Ident,
5099ac24 625 sp: Span,
94222f64
XL
626 print_visibility: impl FnOnce(&mut Self),
627 ) {
628 let (kw, has_bang) = if macro_def.macro_rules {
629 ("macro_rules", true)
630 } else {
631 print_visibility(self);
632 ("macro", false)
633 };
634 self.print_mac_common(
635 Some(MacHeader::Keyword(kw)),
636 has_bang,
637 Some(*ident),
638 macro_def.body.delim(),
639 &macro_def.body.inner_tokens(),
640 true,
5099ac24 641 sp,
94222f64
XL
642 );
643 if macro_def.body.need_semicolon() {
644 self.word(";");
645 }
646 }
647
416331ca
XL
648 fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, depth: usize) {
649 self.maybe_print_comment(path.span.lo());
b039eaaf 650
416331ca
XL
651 for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() {
652 if i > 0 {
653 self.word("::")
654 }
655 self.print_path_segment(segment, colons_before_params);
656 }
b039eaaf
SL
657 }
658
416331ca
XL
659 fn print_path_segment(&mut self, segment: &ast::PathSegment, colons_before_params: bool) {
660 if segment.ident.name != kw::PathRoot {
661 self.print_ident(segment.ident);
662 if let Some(ref args) = segment.args {
663 self.print_generic_args(args, colons_before_params);
664 }
665 }
b039eaaf 666 }
1a4d82fc 667
416331ca 668 fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) {
a1dfa0c6 669 let w = w.into();
e1599b0c 670 // Outer-box is consistent.
416331ca 671 self.cbox(INDENT_UNIT);
e1599b0c 672 // Head-box is inconsistent.
5099ac24 673 self.ibox(0);
e1599b0c 674 // Keyword that starts the head.
1a4d82fc 675 if !w.is_empty() {
416331ca 676 self.word_nbsp(w);
223e47cc 677 }
223e47cc 678 }
223e47cc 679
416331ca
XL
680 fn bopen(&mut self) {
681 self.word("{");
e1599b0c 682 self.end(); // Close the head-box.
1a4d82fc
JJ
683 }
684
a2a8927a
XL
685 fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, close_box: bool) {
686 let has_comment = self.maybe_print_comment(span.hi());
687 if !empty || has_comment {
688 self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize));
689 }
416331ca 690 self.word("}");
1a4d82fc 691 if close_box {
e1599b0c 692 self.end(); // Close the outer-box.
223e47cc 693 }
223e47cc 694 }
223e47cc 695
a2a8927a
XL
696 fn bclose(&mut self, span: rustc_span::Span, empty: bool) {
697 let close_box = true;
698 self.bclose_maybe_open(span, empty, close_box)
223e47cc 699 }
223e47cc 700
416331ca
XL
701 fn break_offset_if_not_bol(&mut self, n: usize, off: isize) {
702 if !self.is_beginning_of_line() {
703 self.break_offset(n, off)
5099ac24
FG
704 } else if off != 0 {
705 if let Some(last_token) = self.last_token_still_buffered() {
706 if last_token.is_hardbreak_tok() {
707 // We do something pretty sketchy here: tuck the nonzero
708 // offset-adjustment we were going to deposit along with the
709 // break into the previous hardbreak.
710 self.replace_last_token_still_buffered(pp::Printer::hardbreak_tok_offset(off));
711 }
712 }
416331ca
XL
713 }
714 }
29967ef6
XL
715
716 fn nonterminal_to_string(&self, nt: &Nonterminal) -> String {
717 match *nt {
718 token::NtExpr(ref e) => self.expr_to_string(e),
719 token::NtMeta(ref e) => self.attr_item_to_string(e),
720 token::NtTy(ref e) => self.ty_to_string(e),
721 token::NtPath(ref e) => self.path_to_string(e),
722 token::NtItem(ref e) => self.item_to_string(e),
723 token::NtBlock(ref e) => self.block_to_string(e),
724 token::NtStmt(ref e) => self.stmt_to_string(e),
725 token::NtPat(ref e) => self.pat_to_string(e),
726 token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
727 token::NtLifetime(e) => e.to_string(),
728 token::NtLiteral(ref e) => self.expr_to_string(e),
29967ef6
XL
729 token::NtVis(ref e) => self.vis_to_string(e),
730 }
731 }
732
733 /// Print the token kind precisely, without converting `$crate` into its respective crate name.
94222f64 734 fn token_kind_to_string(&self, tok: &TokenKind) -> Cow<'static, str> {
29967ef6
XL
735 self.token_kind_to_string_ext(tok, None)
736 }
737
738 fn token_kind_to_string_ext(
739 &self,
740 tok: &TokenKind,
741 convert_dollar_crate: Option<Span>,
94222f64 742 ) -> Cow<'static, str> {
29967ef6 743 match *tok {
94222f64
XL
744 token::Eq => "=".into(),
745 token::Lt => "<".into(),
746 token::Le => "<=".into(),
747 token::EqEq => "==".into(),
748 token::Ne => "!=".into(),
749 token::Ge => ">=".into(),
750 token::Gt => ">".into(),
751 token::Not => "!".into(),
752 token::Tilde => "~".into(),
753 token::OrOr => "||".into(),
754 token::AndAnd => "&&".into(),
755 token::BinOp(op) => binop_to_string(op).into(),
756 token::BinOpEq(op) => format!("{}=", binop_to_string(op)).into(),
29967ef6
XL
757
758 /* Structural symbols */
94222f64
XL
759 token::At => "@".into(),
760 token::Dot => ".".into(),
761 token::DotDot => "..".into(),
762 token::DotDotDot => "...".into(),
763 token::DotDotEq => "..=".into(),
764 token::Comma => ",".into(),
765 token::Semi => ";".into(),
766 token::Colon => ":".into(),
767 token::ModSep => "::".into(),
768 token::RArrow => "->".into(),
769 token::LArrow => "<-".into(),
770 token::FatArrow => "=>".into(),
04454e1e
FG
771 token::OpenDelim(Delimiter::Parenthesis) => "(".into(),
772 token::CloseDelim(Delimiter::Parenthesis) => ")".into(),
773 token::OpenDelim(Delimiter::Bracket) => "[".into(),
774 token::CloseDelim(Delimiter::Bracket) => "]".into(),
775 token::OpenDelim(Delimiter::Brace) => "{".into(),
776 token::CloseDelim(Delimiter::Brace) => "}".into(),
777 token::OpenDelim(Delimiter::Invisible) | token::CloseDelim(Delimiter::Invisible) => {
778 "".into()
779 }
94222f64
XL
780 token::Pound => "#".into(),
781 token::Dollar => "$".into(),
782 token::Question => "?".into(),
783 token::SingleQuote => "'".into(),
29967ef6
XL
784
785 /* Literals */
94222f64 786 token::Literal(lit) => literal_to_string(lit).into(),
29967ef6
XL
787
788 /* Name components */
789 token::Ident(s, is_raw) => {
94222f64 790 IdentPrinter::new(s, is_raw, convert_dollar_crate).to_string().into()
29967ef6 791 }
94222f64 792 token::Lifetime(s) => s.to_string().into(),
29967ef6
XL
793
794 /* Other */
795 token::DocComment(comment_kind, attr_style, data) => {
94222f64 796 doc_comment_to_string(comment_kind, attr_style, data).into()
29967ef6 797 }
94222f64 798 token::Eof => "<eof>".into(),
29967ef6 799
94222f64 800 token::Interpolated(ref nt) => self.nonterminal_to_string(nt).into(),
29967ef6
XL
801 }
802 }
803
804 /// Print the token precisely, without converting `$crate` into its respective crate name.
94222f64 805 fn token_to_string(&self, token: &Token) -> Cow<'static, str> {
29967ef6
XL
806 self.token_to_string_ext(token, false)
807 }
808
94222f64 809 fn token_to_string_ext(&self, token: &Token, convert_dollar_crate: bool) -> Cow<'static, str> {
29967ef6
XL
810 let convert_dollar_crate = convert_dollar_crate.then_some(token.span);
811 self.token_kind_to_string_ext(&token.kind, convert_dollar_crate)
812 }
813
814 fn ty_to_string(&self, ty: &ast::Ty) -> String {
a2a8927a 815 Self::to_string(|s| s.print_type(ty))
29967ef6
XL
816 }
817
818 fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String {
923072b8 819 Self::to_string(|s| s.print_type_bounds(bounds))
29967ef6
XL
820 }
821
822 fn pat_to_string(&self, pat: &ast::Pat) -> String {
a2a8927a 823 Self::to_string(|s| s.print_pat(pat))
29967ef6
XL
824 }
825
826 fn expr_to_string(&self, e: &ast::Expr) -> String {
a2a8927a 827 Self::to_string(|s| s.print_expr(e))
29967ef6
XL
828 }
829
04454e1e
FG
830 fn literal_to_string(&self, lit: &ast::Lit) -> String {
831 Self::to_string(|s| s.print_literal(lit))
832 }
833
29967ef6 834 fn tt_to_string(&self, tt: &TokenTree) -> String {
a2a8927a 835 Self::to_string(|s| s.print_tt(tt, false))
29967ef6
XL
836 }
837
838 fn tts_to_string(&self, tokens: &TokenStream) -> String {
a2a8927a 839 Self::to_string(|s| s.print_tts(tokens, false))
29967ef6
XL
840 }
841
842 fn stmt_to_string(&self, stmt: &ast::Stmt) -> String {
a2a8927a 843 Self::to_string(|s| s.print_stmt(stmt))
29967ef6
XL
844 }
845
846 fn item_to_string(&self, i: &ast::Item) -> String {
a2a8927a 847 Self::to_string(|s| s.print_item(i))
29967ef6
XL
848 }
849
04454e1e
FG
850 fn assoc_item_to_string(&self, i: &ast::AssocItem) -> String {
851 Self::to_string(|s| s.print_assoc_item(i))
852 }
853
854 fn foreign_item_to_string(&self, i: &ast::ForeignItem) -> String {
855 Self::to_string(|s| s.print_foreign_item(i))
856 }
857
29967ef6 858 fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String {
a2a8927a 859 Self::to_string(|s| s.print_generic_params(generic_params))
29967ef6
XL
860 }
861
862 fn path_to_string(&self, p: &ast::Path) -> String {
a2a8927a 863 Self::to_string(|s| s.print_path(p, false, 0))
29967ef6
XL
864 }
865
866 fn path_segment_to_string(&self, p: &ast::PathSegment) -> String {
a2a8927a 867 Self::to_string(|s| s.print_path_segment(p, false))
29967ef6
XL
868 }
869
870 fn vis_to_string(&self, v: &ast::Visibility) -> String {
a2a8927a 871 Self::to_string(|s| s.print_visibility(v))
29967ef6
XL
872 }
873
874 fn block_to_string(&self, blk: &ast::Block) -> String {
a2a8927a 875 Self::to_string(|s| {
29967ef6
XL
876 // Containing cbox, will be closed by `print_block` at `}`.
877 s.cbox(INDENT_UNIT);
878 // Head-ibox, will be closed by `print_block` after `{`.
879 s.ibox(0);
880 s.print_block(blk)
881 })
882 }
883
884 fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String {
a2a8927a 885 Self::to_string(|s| s.print_meta_list_item(li))
29967ef6
XL
886 }
887
888 fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String {
a2a8927a 889 Self::to_string(|s| s.print_attr_item(ai, ai.path.span))
29967ef6
XL
890 }
891
892 fn attribute_to_string(&self, attr: &ast::Attribute) -> String {
a2a8927a 893 Self::to_string(|s| s.print_attribute(attr))
29967ef6
XL
894 }
895
896 fn param_to_string(&self, arg: &ast::Param) -> String {
a2a8927a 897 Self::to_string(|s| s.print_param(arg, false))
29967ef6
XL
898 }
899
a2a8927a 900 fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
29967ef6 901 let mut printer = State::new();
29967ef6
XL
902 f(&mut printer);
903 printer.s.eof()
904 }
416331ca
XL
905}
906
907impl<'a> PrintState<'a> for State<'a> {
908 fn comments(&mut self) -> &mut Option<Comments<'a>> {
909 &mut self.comments
910 }
911
f9f354fc 912 fn print_ident(&mut self, ident: Ident) {
a2a8927a 913 self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
416331ca
XL
914 self.ann.post(self, AnnNode::Ident(&ident))
915 }
916
917 fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) {
918 if colons_before_params {
a2a8927a 919 self.word("::")
416331ca
XL
920 }
921
922 match *args {
923 ast::GenericArgs::AngleBracketed(ref data) => {
a2a8927a 924 self.word("<");
ba9703b0
XL
925 self.commasep(Inconsistent, &data.args, |s, arg| match arg {
926 ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a),
927 ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c),
416331ca 928 });
a2a8927a 929 self.word(">")
416331ca
XL
930 }
931
932 ast::GenericArgs::Parenthesized(ref data) => {
a2a8927a 933 self.word("(");
dfeec247 934 self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty));
a2a8927a 935 self.word(")");
dfeec247 936 self.print_fn_ret_ty(&data.output);
223e47cc 937 }
223e47cc
LB
938 }
939 }
416331ca 940}
223e47cc 941
416331ca 942impl<'a> State<'a> {
29967ef6 943 pub fn new() -> State<'a> {
5099ac24 944 State { s: pp::Printer::new(), comments: None, ann: &NoAnn }
29967ef6
XL
945 }
946
923072b8
FG
947 pub(crate) fn commasep_cmnt<T, F, G>(
948 &mut self,
949 b: Breaks,
950 elts: &[T],
951 mut op: F,
952 mut get_span: G,
953 ) where
416331ca 954 F: FnMut(&mut State<'_>, &T),
dfeec247 955 G: FnMut(&T) -> rustc_span::Span,
1a4d82fc 956 {
416331ca 957 self.rbox(0, b);
1a4d82fc 958 let len = elts.len();
85aaf69f
SL
959 let mut i = 0;
960 for elt in elts {
416331ca
XL
961 self.maybe_print_comment(get_span(elt).hi());
962 op(self, elt);
85aaf69f 963 i += 1;
1a4d82fc 964 if i < len {
a2a8927a 965 self.word(",");
dfeec247 966 self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi()));
416331ca 967 self.space_if_not_bol();
1a4d82fc
JJ
968 }
969 }
416331ca 970 self.end();
1a4d82fc 971 }
223e47cc 972
923072b8 973 pub(crate) fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
7cac9316 974 self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
1a4d82fc 975 }
223e47cc 976
60c5eb7d 977 pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) {
8faf50e0 978 if let Some(lt) = *lifetime {
416331ca
XL
979 self.print_lifetime(lt);
980 self.nbsp();
1a4d82fc 981 }
223e47cc 982 }
223e47cc 983
5099ac24 984 pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocConstraint) {
ba9703b0 985 self.print_ident(constraint.ident);
6a06907d 986 constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false));
a2a8927a 987 self.space();
ba9703b0 988 match &constraint.kind {
5099ac24 989 ast::AssocConstraintKind::Equality { term } => {
ba9703b0 990 self.word_space("=");
5099ac24
FG
991 match term {
992 Term::Ty(ty) => self.print_type(ty),
04454e1e 993 Term::Const(c) => self.print_expr_anon_const(c, &[]),
5099ac24 994 }
ba9703b0 995 }
923072b8
FG
996 ast::AssocConstraintKind::Bound { bounds } => {
997 if !bounds.is_empty() {
998 self.word_nbsp(":");
999 self.print_type_bounds(&bounds);
1000 }
1001 }
ba9703b0
XL
1002 }
1003 }
1004
1005 pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) {
8faf50e0
XL
1006 match generic_arg {
1007 GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
1008 GenericArg::Type(ty) => self.print_type(ty),
9fa01778 1009 GenericArg::Const(ct) => self.print_expr(&ct.value),
8faf50e0
XL
1010 }
1011 }
1012
60c5eb7d 1013 pub fn print_type(&mut self, ty: &ast::Ty) {
416331ca
XL
1014 self.maybe_print_comment(ty.span.lo());
1015 self.ibox(0);
e74abb32 1016 match ty.kind {
c30ab7b3 1017 ast::TyKind::Slice(ref ty) => {
a2a8927a 1018 self.word("[");
416331ca 1019 self.print_type(ty);
a2a8927a 1020 self.word("]");
1a4d82fc 1021 }
7453a54e 1022 ast::TyKind::Ptr(ref mt) => {
a2a8927a 1023 self.word("*");
60c5eb7d 1024 self.print_mt(mt, true);
1a4d82fc 1025 }
7453a54e 1026 ast::TyKind::Rptr(ref lifetime, ref mt) => {
a2a8927a 1027 self.word("&");
416331ca 1028 self.print_opt_lifetime(lifetime);
60c5eb7d 1029 self.print_mt(mt, false);
1a4d82fc 1030 }
5bcae85e 1031 ast::TyKind::Never => {
a2a8927a 1032 self.word("!");
dfeec247 1033 }
7453a54e 1034 ast::TyKind::Tup(ref elts) => {
416331ca 1035 self.popen();
a2a8927a 1036 self.commasep(Inconsistent, &elts, |s, ty| s.print_type(ty));
1a4d82fc 1037 if elts.len() == 1 {
a2a8927a 1038 self.word(",");
1a4d82fc 1039 }
416331ca 1040 self.pclose();
1a4d82fc 1041 }
7453a54e 1042 ast::TyKind::Paren(ref typ) => {
416331ca
XL
1043 self.popen();
1044 self.print_type(typ);
1045 self.pclose();
1a4d82fc 1046 }
7453a54e 1047 ast::TyKind::BareFn(ref f) => {
dfeec247 1048 self.print_ty_fn(f.ext, f.unsafety, &f.decl, None, &f.generic_params);
1a4d82fc 1049 }
7453a54e 1050 ast::TyKind::Path(None, ref path) => {
416331ca 1051 self.print_path(path, false, 0);
c34b1796 1052 }
dfeec247 1053 ast::TyKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, false),
abe05a73 1054 ast::TyKind::TraitObject(ref bounds, syntax) => {
923072b8
FG
1055 if syntax == ast::TraitObjectSyntax::Dyn {
1056 self.word_nbsp("dyn");
1057 }
1058 self.print_type_bounds(bounds);
1a4d82fc 1059 }
8faf50e0 1060 ast::TyKind::ImplTrait(_, ref bounds) => {
923072b8
FG
1061 self.word_nbsp("impl");
1062 self.print_type_bounds(bounds);
5bcae85e 1063 }
94b46f34 1064 ast::TyKind::Array(ref ty, ref length) => {
a2a8927a 1065 self.word("[");
416331ca 1066 self.print_type(ty);
a2a8927a 1067 self.word("; ");
416331ca 1068 self.print_expr(&length.value);
a2a8927a 1069 self.word("]");
1a4d82fc 1070 }
7453a54e 1071 ast::TyKind::Typeof(ref e) => {
a2a8927a 1072 self.word("typeof(");
416331ca 1073 self.print_expr(&e.value);
a2a8927a 1074 self.word(")");
1a4d82fc 1075 }
7453a54e 1076 ast::TyKind::Infer => {
a2a8927a 1077 self.word("_");
3157f602 1078 }
cc61c64b 1079 ast::TyKind::Err => {
416331ca 1080 self.popen();
a2a8927a 1081 self.word("/*ERROR*/");
416331ca 1082 self.pclose();
cc61c64b 1083 }
3157f602 1084 ast::TyKind::ImplicitSelf => {
a2a8927a 1085 self.word("Self");
1a4d82fc 1086 }
ba9703b0 1087 ast::TyKind::MacCall(ref m) => {
416331ca 1088 self.print_mac(m);
e9174d1e 1089 }
532ac7d7 1090 ast::TyKind::CVarArgs => {
a2a8927a 1091 self.word("...");
532ac7d7 1092 }
223e47cc 1093 }
416331ca 1094 self.end();
1a4d82fc
JJ
1095 }
1096
416331ca 1097 fn print_trait_ref(&mut self, t: &ast::TraitRef) {
0531ce1d 1098 self.print_path(&t.path, false, 0)
223e47cc 1099 }
223e47cc 1100
dfeec247 1101 fn print_formal_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
ff7c6d11 1102 if !generic_params.is_empty() {
a2a8927a 1103 self.word("for");
416331ca
XL
1104 self.print_generic_params(generic_params);
1105 self.nbsp();
1a4d82fc 1106 }
85aaf69f 1107 }
1a4d82fc 1108
416331ca
XL
1109 fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
1110 self.print_formal_generic_params(&t.bound_generic_params);
1a4d82fc
JJ
1111 self.print_trait_ref(&t.trait_ref)
1112 }
1113
923072b8 1114 pub(crate) fn print_stmt(&mut self, st: &ast::Stmt) {
416331ca 1115 self.maybe_print_comment(st.span.lo());
e74abb32 1116 match st.kind {
3157f602 1117 ast::StmtKind::Local(ref loc) => {
416331ca
XL
1118 self.print_outer_attributes(&loc.attrs);
1119 self.space_if_not_bol();
1120 self.ibox(INDENT_UNIT);
1121 self.word_nbsp("let");
1122
1123 self.ibox(INDENT_UNIT);
1124 self.print_local_decl(loc);
1125 self.end();
94222f64 1126 if let Some((init, els)) = loc.kind.init_else_opt() {
416331ca
XL
1127 self.nbsp();
1128 self.word_space("=");
1129 self.print_expr(init);
94222f64
XL
1130 if let Some(els) = els {
1131 self.cbox(INDENT_UNIT);
1132 self.ibox(INDENT_UNIT);
a2a8927a 1133 self.word(" else ");
94222f64
XL
1134 self.print_block(els);
1135 }
3157f602 1136 }
a2a8927a 1137 self.word(";");
94222f64 1138 self.end(); // `let` ibox
1a4d82fc 1139 }
416331ca 1140 ast::StmtKind::Item(ref item) => self.print_item(item),
3157f602 1141 ast::StmtKind::Expr(ref expr) => {
416331ca
XL
1142 self.space_if_not_bol();
1143 self.print_expr_outer_attr_style(expr, false);
60c5eb7d 1144 if classify::expr_requires_semi_to_be_stmt(expr) {
a2a8927a 1145 self.word(";");
3157f602 1146 }
1a4d82fc 1147 }
3157f602 1148 ast::StmtKind::Semi(ref expr) => {
74b04a01
XL
1149 self.space_if_not_bol();
1150 self.print_expr_outer_attr_style(expr, false);
a2a8927a 1151 self.word(";");
74b04a01
XL
1152 }
1153 ast::StmtKind::Empty => {
1154 self.space_if_not_bol();
a2a8927a 1155 self.word(";");
1a4d82fc 1156 }
ba9703b0 1157 ast::StmtKind::MacCall(ref mac) => {
416331ca 1158 self.space_if_not_bol();
1b1a35ee
XL
1159 self.print_outer_attributes(&mac.attrs);
1160 self.print_mac(&mac.mac);
1161 if mac.style == ast::MacStmtStyle::Semicolon {
a2a8927a 1162 self.word(";");
223e47cc
LB
1163 }
1164 }
223e47cc 1165 }
1a4d82fc 1166 self.maybe_print_trailing_comment(st.span, None)
223e47cc 1167 }
223e47cc 1168
923072b8 1169 pub(crate) fn print_block(&mut self, blk: &ast::Block) {
1a4d82fc
JJ
1170 self.print_block_with_attrs(blk, &[])
1171 }
970d7e83 1172
923072b8 1173 pub(crate) fn print_block_unclosed_indent(&mut self, blk: &ast::Block) {
416331ca 1174 self.print_block_maybe_unclosed(blk, &[], false)
1a4d82fc 1175 }
223e47cc 1176
923072b8 1177 pub(crate) fn print_block_with_attrs(&mut self, blk: &ast::Block, attrs: &[ast::Attribute]) {
416331ca 1178 self.print_block_maybe_unclosed(blk, attrs, true)
1a4d82fc 1179 }
223e47cc 1180
923072b8 1181 pub(crate) fn print_block_maybe_unclosed(
dfeec247
XL
1182 &mut self,
1183 blk: &ast::Block,
1184 attrs: &[ast::Attribute],
1185 close_box: bool,
1186 ) {
1a4d82fc 1187 match blk.rules {
416331ca 1188 BlockCheckMode::Unsafe(..) => self.word_space("unsafe"),
dfeec247 1189 BlockCheckMode::Default => (),
1a4d82fc 1190 }
416331ca
XL
1191 self.maybe_print_comment(blk.span.lo());
1192 self.ann.pre(self, AnnNode::Block(blk));
1193 self.bopen();
223e47cc 1194
a2a8927a 1195 let has_attrs = self.print_inner_attributes(attrs);
970d7e83 1196
3157f602 1197 for (i, st) in blk.stmts.iter().enumerate() {
e74abb32 1198 match st.kind {
3157f602 1199 ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => {
416331ca
XL
1200 self.maybe_print_comment(st.span.lo());
1201 self.space_if_not_bol();
1202 self.print_expr_outer_attr_style(expr, false);
1203 self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
3157f602 1204 }
416331ca 1205 _ => self.print_stmt(st),
1a4d82fc 1206 }
1a4d82fc 1207 }
3157f602 1208
a2a8927a
XL
1209 let empty = !has_attrs && blk.stmts.is_empty();
1210 self.bclose_maybe_open(blk.span, empty, close_box);
b7449926 1211 self.ann.post(self, AnnNode::Block(blk))
1a4d82fc
JJ
1212 }
1213
94222f64 1214 /// Print a `let pat = expr` expression.
923072b8 1215 pub(crate) fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) {
a2a8927a 1216 self.word("let ");
e1599b0c 1217 self.print_pat(pat);
a2a8927a 1218 self.space();
416331ca 1219 self.word_space("=");
94222f64
XL
1220 let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order());
1221 self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals())
dc9dc135
XL
1222 }
1223
923072b8 1224 pub(crate) fn print_mac(&mut self, m: &ast::MacCall) {
416331ca 1225 self.print_mac_common(
e1599b0c 1226 Some(MacHeader::Path(&m.path)),
416331ca
XL
1227 true,
1228 None,
60c5eb7d 1229 m.args.delim(),
f035d41b 1230 &m.args.inner_tokens(),
416331ca 1231 true,
60c5eb7d 1232 m.span(),
416331ca 1233 );
223e47cc 1234 }
223e47cc 1235
17df50a5
XL
1236 fn print_inline_asm(&mut self, asm: &ast::InlineAsm) {
1237 enum AsmArg<'a> {
1238 Template(String),
1239 Operand(&'a InlineAsmOperand),
94222f64 1240 ClobberAbi(Symbol),
17df50a5
XL
1241 Options(InlineAsmOptions),
1242 }
1243
94222f64 1244 let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&asm.template))];
17df50a5 1245 args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
3c0e092e
XL
1246 for (abi, _) in &asm.clobber_abis {
1247 args.push(AsmArg::ClobberAbi(*abi));
94222f64 1248 }
17df50a5
XL
1249 if !asm.options.is_empty() {
1250 args.push(AsmArg::Options(asm.options));
1251 }
1252
1253 self.popen();
1254 self.commasep(Consistent, &args, |s, arg| match arg {
1255 AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked),
1256 AsmArg::Operand(op) => {
1257 let print_reg_or_class = |s: &mut Self, r: &InlineAsmRegOrRegClass| match r {
1258 InlineAsmRegOrRegClass::Reg(r) => s.print_symbol(*r, ast::StrStyle::Cooked),
1259 InlineAsmRegOrRegClass::RegClass(r) => s.word(r.to_string()),
1260 };
1261 match op {
1262 InlineAsmOperand::In { reg, expr } => {
1263 s.word("in");
1264 s.popen();
1265 print_reg_or_class(s, reg);
1266 s.pclose();
1267 s.space();
1268 s.print_expr(expr);
1269 }
1270 InlineAsmOperand::Out { reg, late, expr } => {
1271 s.word(if *late { "lateout" } else { "out" });
1272 s.popen();
1273 print_reg_or_class(s, reg);
1274 s.pclose();
1275 s.space();
1276 match expr {
1277 Some(expr) => s.print_expr(expr),
1278 None => s.word("_"),
1279 }
1280 }
1281 InlineAsmOperand::InOut { reg, late, expr } => {
1282 s.word(if *late { "inlateout" } else { "inout" });
1283 s.popen();
1284 print_reg_or_class(s, reg);
1285 s.pclose();
1286 s.space();
1287 s.print_expr(expr);
1288 }
1289 InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
1290 s.word(if *late { "inlateout" } else { "inout" });
1291 s.popen();
1292 print_reg_or_class(s, reg);
1293 s.pclose();
1294 s.space();
1295 s.print_expr(in_expr);
1296 s.space();
1297 s.word_space("=>");
1298 match out_expr {
1299 Some(out_expr) => s.print_expr(out_expr),
1300 None => s.word("_"),
1301 }
1302 }
1303 InlineAsmOperand::Const { anon_const } => {
1304 s.word("const");
1305 s.space();
1306 s.print_expr(&anon_const.value);
1307 }
04454e1e 1308 InlineAsmOperand::Sym { sym } => {
17df50a5
XL
1309 s.word("sym");
1310 s.space();
04454e1e
FG
1311 if let Some(qself) = &sym.qself {
1312 s.print_qpath(&sym.path, qself, true);
1313 } else {
1314 s.print_path(&sym.path, true, 0);
1315 }
17df50a5
XL
1316 }
1317 }
1318 }
94222f64
XL
1319 AsmArg::ClobberAbi(abi) => {
1320 s.word("clobber_abi");
1321 s.popen();
1322 s.print_symbol(*abi, ast::StrStyle::Cooked);
1323 s.pclose();
1324 }
17df50a5
XL
1325 AsmArg::Options(opts) => {
1326 s.word("options");
1327 s.popen();
1328 let mut options = vec![];
1329 if opts.contains(InlineAsmOptions::PURE) {
1330 options.push("pure");
1331 }
1332 if opts.contains(InlineAsmOptions::NOMEM) {
1333 options.push("nomem");
1334 }
1335 if opts.contains(InlineAsmOptions::READONLY) {
1336 options.push("readonly");
1337 }
1338 if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
1339 options.push("preserves_flags");
1340 }
1341 if opts.contains(InlineAsmOptions::NORETURN) {
1342 options.push("noreturn");
1343 }
1344 if opts.contains(InlineAsmOptions::NOSTACK) {
1345 options.push("nostack");
1346 }
1347 if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
1348 options.push("att_syntax");
1349 }
136023e0
XL
1350 if opts.contains(InlineAsmOptions::RAW) {
1351 options.push("raw");
1352 }
a2a8927a
XL
1353 if opts.contains(InlineAsmOptions::MAY_UNWIND) {
1354 options.push("may_unwind");
1355 }
17df50a5
XL
1356 s.commasep(Inconsistent, &options, |s, &opt| {
1357 s.word(opt);
1358 });
1359 s.pclose();
1360 }
1361 });
1362 self.pclose();
1363 }
1364
923072b8 1365 pub(crate) fn print_local_decl(&mut self, loc: &ast::Local) {
416331ca 1366 self.print_pat(&loc.pat);
1a4d82fc 1367 if let Some(ref ty) = loc.ty {
416331ca
XL
1368 self.word_space(":");
1369 self.print_type(ty);
1a4d82fc 1370 }
223e47cc 1371 }
223e47cc 1372
923072b8 1373 pub(crate) fn print_name(&mut self, name: Symbol) {
a2a8927a 1374 self.word(name.to_string());
b7449926 1375 self.ann.post(self, AnnNode::Name(&name))
1a4d82fc
JJ
1376 }
1377
dfeec247 1378 fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_params: bool) {
a2a8927a 1379 self.word("<");
416331ca 1380 self.print_type(&qself.ty);
c34b1796 1381 if qself.position > 0 {
a2a8927a 1382 self.space();
416331ca 1383 self.word_space("as");
c34b1796 1384 let depth = path.segments.len() - qself.position;
416331ca 1385 self.print_path(path, false, depth);
c34b1796 1386 }
a2a8927a 1387 self.word(">");
fc512014 1388 for item_segment in &path.segments[qself.position..] {
a2a8927a 1389 self.word("::");
fc512014
XL
1390 self.print_ident(item_segment.ident);
1391 if let Some(ref args) = item_segment.args {
1392 self.print_generic_args(args, colons_before_params)
1393 }
32a655c1 1394 }
85aaf69f
SL
1395 }
1396
923072b8 1397 pub(crate) fn print_pat(&mut self, pat: &ast::Pat) {
416331ca
XL
1398 self.maybe_print_comment(pat.span.lo());
1399 self.ann.pre(self, AnnNode::Pat(pat));
1a4d82fc 1400 /* Pat isn't normalized, but the beauty of it
dfeec247 1401 is that it doesn't matter */
e74abb32 1402 match pat.kind {
a2a8927a 1403 PatKind::Wild => self.word("_"),
f2b60f7d
FG
1404 PatKind::Ident(BindingAnnotation(by_ref, mutbl), ident, ref sub) => {
1405 if by_ref == ByRef::Yes {
1406 self.word_nbsp("ref");
1407 }
1408 if mutbl == Mutability::Mut {
1409 self.word_nbsp("mut");
1a4d82fc 1410 }
416331ca 1411 self.print_ident(ident);
3157f602 1412 if let Some(ref p) = *sub {
a2a8927a
XL
1413 self.space();
1414 self.word_space("@");
416331ca 1415 self.print_pat(p);
3157f602
XL
1416 }
1417 }
17df50a5
XL
1418 PatKind::TupleStruct(ref qself, ref path, ref elts) => {
1419 if let Some(qself) = qself {
1420 self.print_qpath(path, qself, true);
1421 } else {
1422 self.print_path(path, true, 0);
1423 }
416331ca 1424 self.popen();
a2a8927a 1425 self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
416331ca 1426 self.pclose();
1a4d82fc 1427 }
e1599b0c 1428 PatKind::Or(ref pats) => {
a2a8927a 1429 self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(p));
e1599b0c 1430 }
3157f602 1431 PatKind::Path(None, ref path) => {
416331ca 1432 self.print_path(path, true, 0);
7453a54e 1433 }
3157f602 1434 PatKind::Path(Some(ref qself), ref path) => {
416331ca 1435 self.print_qpath(path, qself, false);
d9579d0f 1436 }
17df50a5
XL
1437 PatKind::Struct(ref qself, ref path, ref fields, etc) => {
1438 if let Some(qself) = qself {
1439 self.print_qpath(path, qself, true);
1440 } else {
1441 self.print_path(path, true, 0);
1442 }
416331ca 1443 self.nbsp();
a2a8927a
XL
1444 self.word("{");
1445 let empty = fields.is_empty() && !etc;
1446 if !empty {
1447 self.space();
1448 }
32a655c1 1449 self.commasep_cmnt(
dfeec247 1450 Consistent,
a2a8927a 1451 &fields,
1a4d82fc 1452 |s, f| {
416331ca 1453 s.cbox(INDENT_UNIT);
e1599b0c
XL
1454 if !f.is_shorthand {
1455 s.print_ident(f.ident);
416331ca 1456 s.word_nbsp(":");
1a4d82fc 1457 }
e1599b0c 1458 s.print_pat(&f.pat);
416331ca 1459 s.end();
1a4d82fc 1460 },
dfeec247
XL
1461 |f| f.pat.span,
1462 );
1a4d82fc 1463 if etc {
dfeec247
XL
1464 if !fields.is_empty() {
1465 self.word_space(",");
1466 }
a2a8927a 1467 self.word("..");
416331ca 1468 }
a2a8927a
XL
1469 if !empty {
1470 self.space();
1471 }
1472 self.word("}");
416331ca
XL
1473 }
1474 PatKind::Tuple(ref elts) => {
1475 self.popen();
a2a8927a 1476 self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
416331ca 1477 if elts.len() == 1 {
a2a8927a 1478 self.word(",");
1a4d82fc 1479 }
416331ca 1480 self.pclose();
1a4d82fc 1481 }
7453a54e 1482 PatKind::Box(ref inner) => {
a2a8927a 1483 self.word("box ");
416331ca 1484 self.print_pat(inner);
1a4d82fc 1485 }
7453a54e 1486 PatKind::Ref(ref inner, mutbl) => {
a2a8927a 1487 self.word("&");
f2b60f7d 1488 if mutbl == Mutability::Mut {
a2a8927a 1489 self.word("mut ");
1a4d82fc 1490 }
f2b60f7d 1491 if let PatKind::Ident(ast::BindingAnnotation::MUT, ..) = inner.kind {
fc512014
XL
1492 self.popen();
1493 self.print_pat(inner);
1494 self.pclose();
1495 } else {
1496 self.print_pat(inner);
1497 }
1a4d82fc 1498 }
416331ca 1499 PatKind::Lit(ref e) => self.print_expr(&**e),
8faf50e0 1500 PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
dfeec247
XL
1501 if let Some(e) = begin {
1502 self.print_expr(e);
dfeec247 1503 }
32a655c1 1504 match *end_kind {
a2a8927a
XL
1505 RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."),
1506 RangeEnd::Included(RangeSyntax::DotDotEq) => self.word("..="),
1507 RangeEnd::Excluded => self.word(".."),
1a4d82fc 1508 }
dfeec247
XL
1509 if let Some(e) = end {
1510 self.print_expr(e);
1511 }
416331ca
XL
1512 }
1513 PatKind::Slice(ref elts) => {
a2a8927a
XL
1514 self.word("[");
1515 self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p));
1516 self.word("]");
1a4d82fc 1517 }
a2a8927a 1518 PatKind::Rest => self.word(".."),
0531ce1d 1519 PatKind::Paren(ref inner) => {
416331ca
XL
1520 self.popen();
1521 self.print_pat(inner);
1522 self.pclose();
0531ce1d 1523 }
ba9703b0 1524 PatKind::MacCall(ref m) => self.print_mac(m),
1a4d82fc 1525 }
b7449926 1526 self.ann.post(self, AnnNode::Pat(pat))
1a4d82fc 1527 }
223e47cc 1528
416331ca 1529 fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) {
3157f602
XL
1530 match explicit_self.node {
1531 SelfKind::Value(m) => {
60c5eb7d 1532 self.print_mutability(m, false);
a2a8927a 1533 self.word("self")
1a4d82fc 1534 }
3157f602 1535 SelfKind::Region(ref lt, m) => {
a2a8927a 1536 self.word("&");
416331ca 1537 self.print_opt_lifetime(lt);
60c5eb7d 1538 self.print_mutability(m, false);
a2a8927a 1539 self.word("self")
1a4d82fc 1540 }
3157f602 1541 SelfKind::Explicit(ref typ, m) => {
60c5eb7d 1542 self.print_mutability(m, false);
a2a8927a 1543 self.word("self");
416331ca 1544 self.word_space(":");
7cac9316 1545 self.print_type(typ)
1a4d82fc
JJ
1546 }
1547 }
223e47cc 1548 }
223e47cc 1549
923072b8 1550 pub(crate) fn print_asyncness(&mut self, asyncness: ast::Async) {
8faf50e0 1551 if asyncness.is_async() {
416331ca 1552 self.word_nbsp("async");
8faf50e0 1553 }
8faf50e0
XL
1554 }
1555
923072b8
FG
1556 pub fn print_type_bounds(&mut self, bounds: &[ast::GenericBound]) {
1557 let mut first = true;
1558 for bound in bounds {
1559 if first {
1560 first = false;
1561 } else {
1562 self.nbsp();
1563 self.word_space("+");
1564 }
1a4d82fc 1565
923072b8
FG
1566 match bound {
1567 GenericBound::Trait(tref, modifier) => {
1568 if modifier == &TraitBoundModifier::Maybe {
1569 self.word("?");
1a4d82fc 1570 }
923072b8 1571 self.print_poly_trait_ref(tref);
ff7c6d11 1572 }
923072b8 1573 GenericBound::Outlives(lt) => self.print_lifetime(*lt),
1a4d82fc 1574 }
1a4d82fc
JJ
1575 }
1576 }
223e47cc 1577
923072b8 1578 pub(crate) fn print_lifetime(&mut self, lifetime: ast::Lifetime) {
7cac9316 1579 self.print_name(lifetime.ident.name)
223e47cc 1580 }
223e47cc 1581
923072b8
FG
1582 pub(crate) fn print_lifetime_bounds(&mut self, bounds: &ast::GenericBounds) {
1583 for (i, bound) in bounds.iter().enumerate() {
1584 if i != 0 {
1585 self.word(" + ");
1586 }
1587 match bound {
1588 ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt),
1589 _ => panic!(),
3157f602 1590 }
223e47cc
LB
1591 }
1592 }
223e47cc 1593
923072b8 1594 pub(crate) fn print_generic_params(&mut self, generic_params: &[ast::GenericParam]) {
ff7c6d11 1595 if generic_params.is_empty() {
416331ca 1596 return;
1a4d82fc
JJ
1597 }
1598
a2a8927a 1599 self.word("<");
1a4d82fc 1600
ff7c6d11 1601 self.commasep(Inconsistent, &generic_params, |s, param| {
416331ca
XL
1602 s.print_outer_attributes_inline(&param.attrs);
1603
8faf50e0
XL
1604 match param.kind {
1605 ast::GenericParamKind::Lifetime => {
8faf50e0 1606 let lt = ast::Lifetime { id: param.id, ident: param.ident };
923072b8
FG
1607 s.print_lifetime(lt);
1608 if !param.bounds.is_empty() {
1609 s.word_nbsp(":");
1610 s.print_lifetime_bounds(&param.bounds)
1611 }
9fa01778 1612 }
8faf50e0 1613 ast::GenericParamKind::Type { ref default } => {
416331ca 1614 s.print_ident(param.ident);
923072b8
FG
1615 if !param.bounds.is_empty() {
1616 s.word_nbsp(":");
1617 s.print_type_bounds(&param.bounds);
1618 }
416331ca 1619 if let Some(ref default) = default {
a2a8927a 1620 s.space();
416331ca
XL
1621 s.word_space("=");
1622 s.print_type(default)
8faf50e0
XL
1623 }
1624 }
5869c6ff 1625 ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
416331ca
XL
1626 s.word_space("const");
1627 s.print_ident(param.ident);
a2a8927a 1628 s.space();
416331ca
XL
1629 s.word_space(":");
1630 s.print_type(ty);
923072b8
FG
1631 if !param.bounds.is_empty() {
1632 s.word_nbsp(":");
1633 s.print_type_bounds(&param.bounds);
1634 }
cdc7bbd5 1635 if let Some(ref default) = default {
a2a8927a 1636 s.space();
cdc7bbd5
XL
1637 s.word_space("=");
1638 s.print_expr(&default.value);
5869c6ff 1639 }
9fa01778 1640 }
1a4d82fc 1641 }
416331ca 1642 });
1a4d82fc 1643
a2a8927a 1644 self.word(">");
223e47cc 1645 }
223e47cc 1646
60c5eb7d 1647 pub fn print_mutability(&mut self, mutbl: ast::Mutability, print_const: bool) {
1a4d82fc 1648 match mutbl {
dfeec247
XL
1649 ast::Mutability::Mut => self.word_nbsp("mut"),
1650 ast::Mutability::Not => {
1651 if print_const {
1652 self.word_nbsp("const");
1653 }
1654 }
1a4d82fc
JJ
1655 }
1656 }
1657
923072b8 1658 pub(crate) fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) {
60c5eb7d 1659 self.print_mutability(mt.mutbl, print_const);
7453a54e 1660 self.print_type(&mt.ty)
223e47cc 1661 }
223e47cc 1662
923072b8 1663 pub(crate) fn print_param(&mut self, input: &ast::Param, is_closure: bool) {
416331ca
XL
1664 self.ibox(INDENT_UNIT);
1665
1666 self.print_outer_attributes_inline(&input.attrs);
1667
e74abb32 1668 match input.ty.kind {
416331ca 1669 ast::TyKind::Infer if is_closure => self.print_pat(&input.pat),
1a4d82fc 1670 _ => {
a7813a04 1671 if let Some(eself) = input.to_self() {
416331ca 1672 self.print_explicit_self(&eself);
a7813a04 1673 } else {
e74abb32 1674 let invalid = if let PatKind::Ident(_, ident, _) = input.pat.kind {
5869c6ff 1675 ident.name == kw::Empty
3157f602
XL
1676 } else {
1677 false
1678 };
a7813a04 1679 if !invalid {
416331ca 1680 self.print_pat(&input.pat);
a2a8927a
XL
1681 self.word(":");
1682 self.space();
1a4d82fc 1683 }
416331ca 1684 self.print_type(&input.ty);
1a4d82fc 1685 }
1a4d82fc 1686 }
223e47cc 1687 }
416331ca 1688 self.end();
223e47cc 1689 }
223e47cc 1690
923072b8 1691 pub(crate) fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) {
74b04a01 1692 if let ast::FnRetTy::Ty(ty) = fn_ret_ty {
dfeec247
XL
1693 self.space_if_not_bol();
1694 self.ibox(INDENT_UNIT);
1695 self.word_space("->");
1696 self.print_type(ty);
1697 self.end();
1698 self.maybe_print_comment(ty.span.lo());
1a4d82fc
JJ
1699 }
1700 }
1701
923072b8 1702 pub(crate) fn print_ty_fn(
dfeec247
XL
1703 &mut self,
1704 ext: ast::Extern,
74b04a01 1705 unsafety: ast::Unsafe,
dfeec247 1706 decl: &ast::FnDecl,
f9f354fc 1707 name: Option<Ident>,
dfeec247
XL
1708 generic_params: &[ast::GenericParam],
1709 ) {
416331ca 1710 self.ibox(INDENT_UNIT);
a2a8927a 1711 self.print_formal_generic_params(generic_params);
c34b1796 1712 let generics = ast::Generics {
ff7c6d11 1713 params: Vec::new(),
f035d41b
XL
1714 where_clause: ast::WhereClause {
1715 has_where_token: false,
1716 predicates: Vec::new(),
1717 span: rustc_span::DUMMY_SP,
1718 },
dfeec247 1719 span: rustc_span::DUMMY_SP,
c34b1796 1720 };
74b04a01
XL
1721 let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
1722 self.print_fn(decl, header, name, &generics);
416331ca 1723 self.end();
223e47cc
LB
1724 }
1725
923072b8 1726 pub(crate) fn print_fn_header_info(&mut self, header: ast::FnHeader) {
74b04a01
XL
1727 self.print_constness(header.constness);
1728 self.print_asyncness(header.asyncness);
416331ca 1729 self.print_unsafety(header.unsafety);
b039eaaf 1730
60c5eb7d
XL
1731 match header.ext {
1732 ast::Extern::None => {}
064997fb 1733 ast::Extern::Implicit(_) => {
60c5eb7d
XL
1734 self.word_nbsp("extern");
1735 }
064997fb 1736 ast::Extern::Explicit(abi, _) => {
60c5eb7d
XL
1737 self.word_nbsp("extern");
1738 self.print_literal(&abi.as_lit());
1739 self.nbsp();
1740 }
1a4d82fc
JJ
1741 }
1742
a2a8927a 1743 self.word("fn")
1a4d82fc
JJ
1744 }
1745
923072b8 1746 pub(crate) fn print_unsafety(&mut self, s: ast::Unsafe) {
1a4d82fc 1747 match s {
74b04a01
XL
1748 ast::Unsafe::No => {}
1749 ast::Unsafe::Yes(_) => self.word_nbsp("unsafe"),
1a4d82fc 1750 }
223e47cc 1751 }
abe05a73 1752
923072b8 1753 pub(crate) fn print_constness(&mut self, s: ast::Const) {
dfeec247 1754 match s {
74b04a01
XL
1755 ast::Const::No => {}
1756 ast::Const::Yes(_) => self.word_nbsp("const"),
dfeec247
XL
1757 }
1758 }
1759
923072b8 1760 pub(crate) fn print_is_auto(&mut self, s: ast::IsAuto) {
abe05a73
XL
1761 match s {
1762 ast::IsAuto::Yes => self.word_nbsp("auto"),
416331ca 1763 ast::IsAuto::No => {}
abe05a73
XL
1764 }
1765 }
223e47cc 1766}