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