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