1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 pub use self::AnnNode
::*;
14 use ast
::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}
;
15 use ast
::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}
;
17 use util
::parser
::{self, AssocOp, Fixity}
;
19 use codemap
::{self, CodeMap}
;
20 use syntax_pos
::{self, BytePos}
;
21 use parse
::token
::{self, BinOpToken, Token}
;
22 use parse
::lexer
::comments
;
23 use parse
::{self, ParseSess}
;
24 use print
::pp
::{self, Breaks}
;
25 use print
::pp
::Breaks
::{Consistent, Inconsistent}
;
28 use symbol
::{Symbol, keywords}
;
29 use syntax_pos
::DUMMY_SP
;
30 use tokenstream
::{self, TokenStream, TokenTree}
;
33 use std
::io
::{self, Write, Read}
;
34 use std
::iter
::{self, Peekable}
;
37 pub enum AnnNode
<'a
> {
38 NodeIdent(&'a ast
::Ident
),
39 NodeName(&'a ast
::Name
),
40 NodeBlock(&'a ast
::Block
),
41 NodeItem(&'a ast
::Item
),
42 NodeSubItem(ast
::NodeId
),
43 NodeExpr(&'a ast
::Expr
),
44 NodePat(&'a ast
::Pat
),
48 fn pre(&self, _state
: &mut State
, _node
: AnnNode
) -> io
::Result
<()> { Ok(()) }
49 fn post(&self, _state
: &mut State
, _node
: AnnNode
) -> io
::Result
<()> { Ok(()) }
52 #[derive(Copy, Clone)]
55 impl PpAnn
for NoAnn {}
57 pub struct State
<'a
> {
58 pub s
: pp
::Printer
<'a
>,
59 cm
: Option
<&'a CodeMap
>,
60 comments
: Option
<Vec
<comments
::Comment
> >,
61 literals
: Peekable
<vec
::IntoIter
<comments
::Literal
>>,
63 boxes
: Vec
<pp
::Breaks
>,
67 fn rust_printer
<'a
>(writer
: Box
<Write
+'a
>, ann
: &'a PpAnn
) -> State
<'a
> {
69 s
: pp
::mk_printer(writer
, DEFAULT_COLUMNS
),
72 literals
: vec
![].into_iter().peekable(),
79 pub const INDENT_UNIT
: usize = 4;
81 pub const DEFAULT_COLUMNS
: usize = 78;
83 /// Requires you to pass an input filename and reader so that
84 /// it can scan the input text for comments and literals to
86 pub fn print_crate
<'a
>(cm
: &'a CodeMap
,
93 is_expanded
: bool
) -> io
::Result
<()> {
94 let mut s
= State
::new_from_input(cm
, sess
, filename
, input
, out
, ann
, is_expanded
);
96 if is_expanded
&& !std_inject
::injected_crate_name(krate
).is_none() {
97 // We need to print `#![no_std]` (and its feature gate) so that
98 // compiling pretty-printed source won't inject libstd again.
99 // However we don't want these attributes in the AST because
100 // of the feature gate, so we fake them up here.
102 // #![feature(prelude_import)]
103 let prelude_import_meta
= attr
::mk_list_word_item(Symbol
::intern("prelude_import"));
104 let list
= attr
::mk_list_item(Symbol
::intern("feature"), vec
![prelude_import_meta
]);
105 let fake_attr
= attr
::mk_attr_inner(DUMMY_SP
, attr
::mk_attr_id(), list
);
106 s
.print_attribute(&fake_attr
)?
;
109 let no_std_meta
= attr
::mk_word_item(Symbol
::intern("no_std"));
110 let fake_attr
= attr
::mk_attr_inner(DUMMY_SP
, attr
::mk_attr_id(), no_std_meta
);
111 s
.print_attribute(&fake_attr
)?
;
114 s
.print_mod(&krate
.module
, &krate
.attrs
)?
;
115 s
.print_remaining_comments()?
;
120 pub fn new_from_input(cm
: &'a CodeMap
,
126 is_expanded
: bool
) -> State
<'a
> {
127 let (cmnts
, lits
) = comments
::gather_comments_and_literals(sess
, filename
, input
);
134 // If the code is post expansion, don't use the table of
135 // literals, since it doesn't correspond with the literals
136 // in the AST anymore.
137 if is_expanded { None }
else { Some(lits) }
)
140 pub fn new(cm
: &'a CodeMap
,
143 comments
: Option
<Vec
<comments
::Comment
>>,
144 literals
: Option
<Vec
<comments
::Literal
>>) -> State
<'a
> {
146 s
: pp
::mk_printer(out
, DEFAULT_COLUMNS
),
149 literals
: literals
.unwrap_or_default().into_iter().peekable(),
157 pub fn to_string
<F
>(f
: F
) -> String
where
158 F
: FnOnce(&mut State
) -> io
::Result
<()>,
160 let mut wr
= Vec
::new();
163 let mut printer
= rust_printer(Box
::new(&mut wr
), &ann
);
164 f(&mut printer
).unwrap();
165 printer
.s
.eof().unwrap();
167 String
::from_utf8(wr
).unwrap()
170 fn binop_to_string(op
: BinOpToken
) -> &'
static str {
176 token
::Percent
=> "%",
185 pub fn token_to_string(tok
: &Token
) -> String
{
187 token
::Eq
=> "=".to_string(),
188 token
::Lt
=> "<".to_string(),
189 token
::Le
=> "<=".to_string(),
190 token
::EqEq
=> "==".to_string(),
191 token
::Ne
=> "!=".to_string(),
192 token
::Ge
=> ">=".to_string(),
193 token
::Gt
=> ">".to_string(),
194 token
::Not
=> "!".to_string(),
195 token
::Tilde
=> "~".to_string(),
196 token
::OrOr
=> "||".to_string(),
197 token
::AndAnd
=> "&&".to_string(),
198 token
::BinOp(op
) => binop_to_string(op
).to_string(),
199 token
::BinOpEq(op
) => format
!("{}=", binop_to_string(op
)),
201 /* Structural symbols */
202 token
::At
=> "@".to_string(),
203 token
::Dot
=> ".".to_string(),
204 token
::DotDot
=> "..".to_string(),
205 token
::DotDotDot
=> "...".to_string(),
206 token
::DotDotEq
=> "..=".to_string(),
207 token
::DotEq
=> ".=".to_string(),
208 token
::Comma
=> ",".to_string(),
209 token
::Semi
=> ";".to_string(),
210 token
::Colon
=> ":".to_string(),
211 token
::ModSep
=> "::".to_string(),
212 token
::RArrow
=> "->".to_string(),
213 token
::LArrow
=> "<-".to_string(),
214 token
::FatArrow
=> "=>".to_string(),
215 token
::OpenDelim(token
::Paren
) => "(".to_string(),
216 token
::CloseDelim(token
::Paren
) => ")".to_string(),
217 token
::OpenDelim(token
::Bracket
) => "[".to_string(),
218 token
::CloseDelim(token
::Bracket
) => "]".to_string(),
219 token
::OpenDelim(token
::Brace
) => "{".to_string(),
220 token
::CloseDelim(token
::Brace
) => "}".to_string(),
221 token
::OpenDelim(token
::NoDelim
) |
222 token
::CloseDelim(token
::NoDelim
) => " ".to_string(),
223 token
::Pound
=> "#".to_string(),
224 token
::Dollar
=> "$".to_string(),
225 token
::Question
=> "?".to_string(),
228 token
::Literal(lit
, suf
) => {
229 let mut out
= match lit
{
230 token
::Byte(b
) => format
!("b'{}'", b
),
231 token
::Char(c
) => format
!("'{}'", c
),
233 token
::Integer(c
) => c
.to_string(),
234 token
::Str_(s
) => format
!("\"{}\"", s
),
235 token
::StrRaw(s
, n
) => format
!("r{delim}\"{string}\"{delim}",
236 delim
=repeat("#", n
),
238 token
::ByteStr(v
) => format
!("b\"{}\"", v
),
239 token
::ByteStrRaw(s
, n
) => format
!("br{delim}\"{string}\"{delim}",
240 delim
=repeat("#", n
),
244 if let Some(s
) = suf
{
245 out
.push_str(&s
.as_str())
251 /* Name components */
252 token
::Ident(s
) => s
.to_string(),
253 token
::Lifetime(s
) => s
.to_string(),
254 token
::Underscore
=> "_".to_string(),
257 token
::DocComment(s
) => s
.to_string(),
258 token
::Eof
=> "<eof>".to_string(),
259 token
::Whitespace
=> " ".to_string(),
260 token
::Comment
=> "/* */".to_string(),
261 token
::Shebang(s
) => format
!("/* shebang: {}*/", s
),
263 token
::Interpolated(ref nt
) => match nt
.0 {
264 token
::NtExpr(ref e
) => expr_to_string(e
),
265 token
::NtMeta(ref e
) => meta_item_to_string(e
),
266 token
::NtTy(ref e
) => ty_to_string(e
),
267 token
::NtPath(ref e
) => path_to_string(e
),
268 token
::NtItem(ref e
) => item_to_string(e
),
269 token
::NtBlock(ref e
) => block_to_string(e
),
270 token
::NtStmt(ref e
) => stmt_to_string(e
),
271 token
::NtPat(ref e
) => pat_to_string(e
),
272 token
::NtIdent(ref e
) => ident_to_string(e
.node
),
273 token
::NtTT(ref tree
) => tt_to_string(tree
.clone()),
274 token
::NtArm(ref e
) => arm_to_string(e
),
275 token
::NtImplItem(ref e
) => impl_item_to_string(e
),
276 token
::NtTraitItem(ref e
) => trait_item_to_string(e
),
277 token
::NtGenerics(ref e
) => generics_to_string(e
),
278 token
::NtWhereClause(ref e
) => where_clause_to_string(e
),
279 token
::NtArg(ref e
) => arg_to_string(e
),
280 token
::NtVis(ref e
) => vis_to_string(e
),
285 pub fn ty_to_string(ty
: &ast
::Ty
) -> String
{
286 to_string(|s
| s
.print_type(ty
))
289 pub fn bounds_to_string(bounds
: &[ast
::TyParamBound
]) -> String
{
290 to_string(|s
| s
.print_bounds("", bounds
))
293 pub fn pat_to_string(pat
: &ast
::Pat
) -> String
{
294 to_string(|s
| s
.print_pat(pat
))
297 pub fn arm_to_string(arm
: &ast
::Arm
) -> String
{
298 to_string(|s
| s
.print_arm(arm
))
301 pub fn expr_to_string(e
: &ast
::Expr
) -> String
{
302 to_string(|s
| s
.print_expr(e
))
305 pub fn lifetime_to_string(e
: &ast
::Lifetime
) -> String
{
306 to_string(|s
| s
.print_lifetime(e
))
309 pub fn tt_to_string(tt
: tokenstream
::TokenTree
) -> String
{
310 to_string(|s
| s
.print_tt(tt
))
313 pub fn tts_to_string(tts
: &[tokenstream
::TokenTree
]) -> String
{
314 to_string(|s
| s
.print_tts(tts
.iter().cloned().collect()))
317 pub fn tokens_to_string(tokens
: TokenStream
) -> String
{
318 to_string(|s
| s
.print_tts(tokens
))
321 pub fn stmt_to_string(stmt
: &ast
::Stmt
) -> String
{
322 to_string(|s
| s
.print_stmt(stmt
))
325 pub fn attr_to_string(attr
: &ast
::Attribute
) -> String
{
326 to_string(|s
| s
.print_attribute(attr
))
329 pub fn item_to_string(i
: &ast
::Item
) -> String
{
330 to_string(|s
| s
.print_item(i
))
333 pub fn impl_item_to_string(i
: &ast
::ImplItem
) -> String
{
334 to_string(|s
| s
.print_impl_item(i
))
337 pub fn trait_item_to_string(i
: &ast
::TraitItem
) -> String
{
338 to_string(|s
| s
.print_trait_item(i
))
341 pub fn generics_to_string(generics
: &ast
::Generics
) -> String
{
342 to_string(|s
| s
.print_generics(generics
))
345 pub fn where_clause_to_string(i
: &ast
::WhereClause
) -> String
{
346 to_string(|s
| s
.print_where_clause(i
))
349 pub fn fn_block_to_string(p
: &ast
::FnDecl
) -> String
{
350 to_string(|s
| s
.print_fn_block_args(p
))
353 pub fn path_to_string(p
: &ast
::Path
) -> String
{
354 to_string(|s
| s
.print_path(p
, false, 0, false))
357 pub fn path_segment_to_string(p
: &ast
::PathSegment
) -> String
{
358 to_string(|s
| s
.print_path_segment(p
, false))
361 pub fn ident_to_string(id
: ast
::Ident
) -> String
{
362 to_string(|s
| s
.print_ident(id
))
365 pub fn vis_to_string(v
: &ast
::Visibility
) -> String
{
366 to_string(|s
| s
.print_visibility(v
))
369 pub fn fun_to_string(decl
: &ast
::FnDecl
,
370 unsafety
: ast
::Unsafety
,
371 constness
: ast
::Constness
,
373 generics
: &ast
::Generics
)
377 s
.print_fn(decl
, unsafety
, constness
, Abi
::Rust
, Some(name
),
378 generics
, &ast
::Visibility
::Inherited
)?
;
379 s
.end()?
; // Close the head box
380 s
.end() // Close the outer box
384 pub fn block_to_string(blk
: &ast
::Block
) -> String
{
386 // containing cbox, will be closed by print-block at }
387 s
.cbox(INDENT_UNIT
)?
;
388 // head-ibox, will be closed by print-block after {
394 pub fn meta_list_item_to_string(li
: &ast
::NestedMetaItem
) -> String
{
395 to_string(|s
| s
.print_meta_list_item(li
))
398 pub fn meta_item_to_string(mi
: &ast
::MetaItem
) -> String
{
399 to_string(|s
| s
.print_meta_item(mi
))
402 pub fn attribute_to_string(attr
: &ast
::Attribute
) -> String
{
403 to_string(|s
| s
.print_attribute(attr
))
406 pub fn lit_to_string(l
: &ast
::Lit
) -> String
{
407 to_string(|s
| s
.print_literal(l
))
410 pub fn variant_to_string(var
: &ast
::Variant
) -> String
{
411 to_string(|s
| s
.print_variant(var
))
414 pub fn arg_to_string(arg
: &ast
::Arg
) -> String
{
415 to_string(|s
| s
.print_arg(arg
, false))
418 pub fn mac_to_string(arg
: &ast
::Mac
) -> String
{
419 to_string(|s
| s
.print_mac(arg
, ::parse
::token
::Paren
))
422 pub fn visibility_qualified(vis
: &ast
::Visibility
, s
: &str) -> String
{
423 format
!("{}{}", to_string(|s
| s
.print_visibility(vis
)), s
)
426 pub trait PrintState
<'a
> {
427 fn writer(&mut self) -> &mut pp
::Printer
<'a
>;
428 fn boxes(&mut self) -> &mut Vec
<pp
::Breaks
>;
429 fn comments(&mut self) -> &mut Option
<Vec
<comments
::Comment
>>;
430 fn cur_cmnt(&mut self) -> &mut usize;
431 fn cur_lit(&mut self) -> Option
<&comments
::Literal
>;
432 fn bump_lit(&mut self) -> Option
<comments
::Literal
>;
434 fn word_space(&mut self, w
: &str) -> io
::Result
<()> {
435 self.writer().word(w
)?
;
436 self.writer().space()
439 fn popen(&mut self) -> io
::Result
<()> { self.writer().word("(") }
441 fn pclose(&mut self) -> io
::Result
<()> { self.writer().word(")") }
443 fn is_begin(&mut self) -> bool
{
444 match self.writer().last_token() {
445 pp
::Token
::Begin(_
) => true,
450 fn is_end(&mut self) -> bool
{
451 match self.writer().last_token() {
452 pp
::Token
::End
=> true,
457 // is this the beginning of a line?
458 fn is_bol(&mut self) -> bool
{
459 self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok()
462 fn hardbreak_if_not_bol(&mut self) -> io
::Result
<()> {
464 self.writer().hardbreak()?
470 fn rbox(&mut self, u
: usize, b
: pp
::Breaks
) -> io
::Result
<()> {
471 self.boxes().push(b
);
472 self.writer().rbox(u
, b
)
475 fn ibox(&mut self, u
: usize) -> io
::Result
<()> {
476 self.boxes().push(pp
::Breaks
::Inconsistent
);
477 self.writer().ibox(u
)
480 fn end(&mut self) -> io
::Result
<()> {
481 self.boxes().pop().unwrap();
485 fn commasep
<T
, F
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
) -> io
::Result
<()>
486 where F
: FnMut(&mut Self, &T
) -> io
::Result
<()>,
489 let mut first
= true;
491 if first { first = false; }
else { self.word_space(",")?; }
497 fn next_lit(&mut self, pos
: BytePos
) -> Option
<comments
::Literal
> {
498 while let Some(ltrl
) = self.cur_lit().cloned() {
499 if ltrl
.pos
> pos { break; }
501 // we don't need the value here since we're forced to clone cur_lit
502 // due to lack of NLL.
512 fn maybe_print_comment(&mut self, pos
: BytePos
) -> io
::Result
<()> {
513 while let Some(ref cmnt
) = self.next_comment() {
515 self.print_comment(cmnt
)?
;
523 fn print_comment(&mut self,
524 cmnt
: &comments
::Comment
) -> io
::Result
<()> {
525 let r
= match cmnt
.style
{
527 assert_eq
!(cmnt
.lines
.len(), 1);
528 self.writer().zerobreak()?
;
529 self.writer().word(&cmnt
.lines
[0])?
;
530 self.writer().zerobreak()
532 comments
::Isolated
=> {
533 self.hardbreak_if_not_bol()?
;
534 for line
in &cmnt
.lines
{
535 // Don't print empty lines because they will end up as trailing
537 if !line
.is_empty() {
538 self.writer().word(&line
[..])?
;
540 self.writer().hardbreak()?
;
544 comments
::Trailing
=> {
546 self.writer().word(" ")?
;
548 if cmnt
.lines
.len() == 1 {
549 self.writer().word(&cmnt
.lines
[0])?
;
550 self.writer().hardbreak()
553 for line
in &cmnt
.lines
{
554 if !line
.is_empty() {
555 self.writer().word(&line
[..])?
;
557 self.writer().hardbreak()?
;
562 comments
::BlankLine
=> {
563 // We need to do at least one, possibly two hardbreaks.
564 let is_semi
= match self.writer().last_token() {
565 pp
::Token
::String(s
, _
) => ";" == s
,
568 if is_semi
|| self.is_begin() || self.is_end() {
569 self.writer().hardbreak()?
;
571 self.writer().hardbreak()
576 *self.cur_cmnt() = *self.cur_cmnt() + 1;
583 fn next_comment(&mut self) -> Option
<comments
::Comment
> {
584 let cur_cmnt
= *self.cur_cmnt();
585 match *self.comments() {
587 if cur_cmnt
< cmnts
.len() {
588 Some(cmnts
[cur_cmnt
].clone())
597 fn print_literal(&mut self, lit
: &ast
::Lit
) -> io
::Result
<()> {
598 self.maybe_print_comment(lit
.span
.lo())?
;
599 if let Some(ltrl
) = self.next_lit(lit
.span
.lo()) {
600 return self.writer().word(<rl
.lit
);
603 ast
::LitKind
::Str(st
, style
) => self.print_string(&st
.as_str(), style
),
604 ast
::LitKind
::Byte(byte
) => {
605 let mut res
= String
::from("b'");
606 res
.extend(ascii
::escape_default(byte
).map(|c
| c
as char));
608 self.writer().word(&res
[..])
610 ast
::LitKind
::Char(ch
) => {
611 let mut res
= String
::from("'");
612 res
.extend(ch
.escape_default());
614 self.writer().word(&res
[..])
616 ast
::LitKind
::Int(i
, t
) => {
618 ast
::LitIntType
::Signed(st
) => {
619 self.writer().word(&st
.val_to_string(i
as i128
))
621 ast
::LitIntType
::Unsigned(ut
) => {
622 self.writer().word(&ut
.val_to_string(i
))
624 ast
::LitIntType
::Unsuffixed
=> {
625 self.writer().word(&format
!("{}", i
))
629 ast
::LitKind
::Float(ref f
, t
) => {
630 self.writer().word(&format
!("{}{}", &f
, t
.ty_to_string()))
632 ast
::LitKind
::FloatUnsuffixed(ref f
) => self.writer().word(&f
.as_str()),
633 ast
::LitKind
::Bool(val
) => {
634 if val { self.writer().word("true") }
else { self.writer().word("false") }
636 ast
::LitKind
::ByteStr(ref v
) => {
637 let mut escaped
: String
= String
::new();
638 for &ch
in v
.iter() {
639 escaped
.extend(ascii
::escape_default(ch
)
640 .map(|c
| c
as char));
642 self.writer().word(&format
!("b\"{}\"", escaped
))
647 fn print_string(&mut self, st
: &str,
648 style
: ast
::StrStyle
) -> io
::Result
<()> {
649 let st
= match style
{
650 ast
::StrStyle
::Cooked
=> {
651 (format
!("\"{}\"", parse
::escape_default(st
)))
653 ast
::StrStyle
::Raw(n
) => {
654 (format
!("r{delim}\"{string}\"{delim}",
655 delim
=repeat("#", n
),
659 self.writer().word(&st
[..])
662 fn print_inner_attributes(&mut self,
663 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
664 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, true)
667 fn print_inner_attributes_no_trailing_hardbreak(&mut self,
668 attrs
: &[ast
::Attribute
])
670 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, false)
673 fn print_outer_attributes(&mut self,
674 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
675 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, false, true)
678 fn print_inner_attributes_inline(&mut self,
679 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
680 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, true, true)
683 fn print_outer_attributes_inline(&mut self,
684 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
685 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, true, true)
688 fn print_either_attributes(&mut self,
689 attrs
: &[ast
::Attribute
],
690 kind
: ast
::AttrStyle
,
692 trailing_hardbreak
: bool
) -> io
::Result
<()> {
695 if attr
.style
== kind
{
696 self.print_attribute_inline(attr
, is_inline
)?
;
703 if count
> 0 && trailing_hardbreak
&& !is_inline
{
704 self.hardbreak_if_not_bol()?
;
709 fn print_attribute(&mut self, attr
: &ast
::Attribute
) -> io
::Result
<()> {
710 self.print_attribute_inline(attr
, false)
713 fn print_attribute_inline(&mut self, attr
: &ast
::Attribute
,
714 is_inline
: bool
) -> io
::Result
<()> {
716 self.hardbreak_if_not_bol()?
;
718 self.maybe_print_comment(attr
.span
.lo())?
;
719 if attr
.is_sugared_doc
{
720 self.writer().word(&attr
.value_str().unwrap().as_str())?
;
721 self.writer().hardbreak()
724 ast
::AttrStyle
::Inner
=> self.writer().word("#![")?
,
725 ast
::AttrStyle
::Outer
=> self.writer().word("#[")?
,
727 if let Some(mi
) = attr
.meta() {
728 self.print_meta_item(&mi
)?
730 for (i
, segment
) in attr
.path
.segments
.iter().enumerate() {
732 self.writer().word("::")?
734 if segment
.identifier
.name
!= keywords
::CrateRoot
.name() &&
735 segment
.identifier
.name
!= keywords
::DollarCrate
.name() {
736 self.writer().word(&segment
.identifier
.name
.as_str())?
;
739 self.writer().space()?
;
740 self.print_tts(attr
.tokens
.clone())?
;
742 self.writer().word("]")
746 fn print_meta_list_item(&mut self, item
: &ast
::NestedMetaItem
) -> io
::Result
<()> {
748 ast
::NestedMetaItemKind
::MetaItem(ref mi
) => {
749 self.print_meta_item(mi
)
751 ast
::NestedMetaItemKind
::Literal(ref lit
) => {
752 self.print_literal(lit
)
757 fn print_meta_item(&mut self, item
: &ast
::MetaItem
) -> io
::Result
<()> {
758 self.ibox(INDENT_UNIT
)?
;
760 ast
::MetaItemKind
::Word
=> {
761 self.writer().word(&item
.name
.as_str())?
;
763 ast
::MetaItemKind
::NameValue(ref value
) => {
764 self.word_space(&item
.name
.as_str())?
;
765 self.word_space("=")?
;
766 self.print_literal(value
)?
;
768 ast
::MetaItemKind
::List(ref items
) => {
769 self.writer().word(&item
.name
.as_str())?
;
771 self.commasep(Consistent
,
773 |s
, i
| s
.print_meta_list_item(i
))?
;
780 /// This doesn't deserve to be called "pretty" printing, but it should be
781 /// meaning-preserving. A quick hack that might help would be to look at the
782 /// spans embedded in the TTs to decide where to put spaces and newlines.
783 /// But it'd be better to parse these according to the grammar of the
784 /// appropriate macro, transcribe back into the grammar we just parsed from,
785 /// and then pretty-print the resulting AST nodes (so, e.g., we print
786 /// expression arguments as expressions). It can be done! I think.
787 fn print_tt(&mut self, tt
: tokenstream
::TokenTree
) -> io
::Result
<()> {
789 TokenTree
::Token(_
, ref tk
) => {
790 self.writer().word(&token_to_string(tk
))?
;
792 parse
::token
::DocComment(..) => {
793 self.writer().hardbreak()
798 TokenTree
::Delimited(_
, ref delimed
) => {
799 self.writer().word(&token_to_string(&delimed
.open_token()))?
;
800 self.writer().space()?
;
801 self.print_tts(delimed
.stream())?
;
802 self.writer().space()?
;
803 self.writer().word(&token_to_string(&delimed
.close_token()))
808 fn print_tts(&mut self, tts
: tokenstream
::TokenStream
) -> io
::Result
<()> {
810 for (i
, tt
) in tts
.into_trees().enumerate() {
812 self.writer().space()?
;
819 fn space_if_not_bol(&mut self) -> io
::Result
<()> {
820 if !self.is_bol() { self.writer().space()?; }
824 fn nbsp(&mut self) -> io
::Result
<()> { self.writer().word(" ") }
827 impl<'a
> PrintState
<'a
> for State
<'a
> {
828 fn writer(&mut self) -> &mut pp
::Printer
<'a
> {
832 fn boxes(&mut self) -> &mut Vec
<pp
::Breaks
> {
836 fn comments(&mut self) -> &mut Option
<Vec
<comments
::Comment
>> {
840 fn cur_cmnt(&mut self) -> &mut usize {
844 fn cur_lit(&mut self) -> Option
<&comments
::Literal
> {
848 fn bump_lit(&mut self) -> Option
<comments
::Literal
> {
854 pub fn cbox(&mut self, u
: usize) -> io
::Result
<()> {
855 self.boxes
.push(pp
::Breaks
::Consistent
);
859 pub fn word_nbsp(&mut self, w
: &str) -> io
::Result
<()> {
864 pub fn head(&mut self, w
: &str) -> io
::Result
<()> {
865 // outer-box is consistent
866 self.cbox(INDENT_UNIT
)?
;
867 // head-box is inconsistent
868 self.ibox(w
.len() + 1)?
;
869 // keyword that starts the head
876 pub fn bopen(&mut self) -> io
::Result
<()> {
878 self.end() // close the head-box
881 pub fn bclose_(&mut self, span
: syntax_pos
::Span
,
882 indented
: usize) -> io
::Result
<()> {
883 self.bclose_maybe_open(span
, indented
, true)
885 pub fn bclose_maybe_open(&mut self, span
: syntax_pos
::Span
,
886 indented
: usize, close_box
: bool
) -> io
::Result
<()> {
887 self.maybe_print_comment(span
.hi())?
;
888 self.break_offset_if_not_bol(1, -(indented
as isize))?
;
891 self.end()?
; // close the outer-box
895 pub fn bclose(&mut self, span
: syntax_pos
::Span
) -> io
::Result
<()> {
896 self.bclose_(span
, INDENT_UNIT
)
899 pub fn in_cbox(&self) -> bool
{
900 match self.boxes
.last() {
901 Some(&last_box
) => last_box
== pp
::Breaks
::Consistent
,
906 pub fn break_offset_if_not_bol(&mut self, n
: usize,
907 off
: isize) -> io
::Result
<()> {
909 self.s
.break_offset(n
, off
)
911 if off
!= 0 && self.s
.last_token().is_hardbreak_tok() {
912 // We do something pretty sketchy here: tuck the nonzero
913 // offset-adjustment we were going to deposit along with the
914 // break into the previous hardbreak.
915 self.s
.replace_last_token(pp
::Printer
::hardbreak_tok_offset(off
));
921 // Synthesizes a comment that was not textually present in the original source
923 pub fn synth_comment(&mut self, text
: String
) -> io
::Result
<()> {
926 self.s
.word(&text
[..])?
;
933 pub fn commasep_cmnt
<T
, F
, G
>(&mut self,
937 mut get_span
: G
) -> io
::Result
<()> where
938 F
: FnMut(&mut State
, &T
) -> io
::Result
<()>,
939 G
: FnMut(&T
) -> syntax_pos
::Span
,
942 let len
= elts
.len();
945 self.maybe_print_comment(get_span(elt
).hi())?
;
950 self.maybe_print_trailing_comment(get_span(elt
),
951 Some(get_span(&elts
[i
]).hi()))?
;
952 self.space_if_not_bol()?
;
958 pub fn commasep_exprs(&mut self, b
: Breaks
,
959 exprs
: &[P
<ast
::Expr
>]) -> io
::Result
<()> {
960 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(e
), |e
| e
.span
)
963 pub fn print_mod(&mut self, _mod
: &ast
::Mod
,
964 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
965 self.print_inner_attributes(attrs
)?
;
966 for item
in &_mod
.items
{
967 self.print_item(item
)?
;
972 pub fn print_foreign_mod(&mut self, nmod
: &ast
::ForeignMod
,
973 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
974 self.print_inner_attributes(attrs
)?
;
975 for item
in &nmod
.items
{
976 self.print_foreign_item(item
)?
;
981 pub fn print_opt_lifetime(&mut self,
982 lifetime
: &Option
<ast
::Lifetime
>) -> io
::Result
<()> {
983 if let Some(l
) = *lifetime
{
984 self.print_lifetime(&l
)?
;
990 pub fn print_type(&mut self, ty
: &ast
::Ty
) -> io
::Result
<()> {
991 self.maybe_print_comment(ty
.span
.lo())?
;
994 ast
::TyKind
::Slice(ref ty
) => {
996 self.print_type(ty
)?
;
999 ast
::TyKind
::Ptr(ref mt
) => {
1002 ast
::Mutability
::Mutable
=> self.word_nbsp("mut")?
,
1003 ast
::Mutability
::Immutable
=> self.word_nbsp("const")?
,
1005 self.print_type(&mt
.ty
)?
;
1007 ast
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
1009 self.print_opt_lifetime(lifetime
)?
;
1012 ast
::TyKind
::Never
=> {
1015 ast
::TyKind
::Tup(ref elts
) => {
1017 self.commasep(Inconsistent
, &elts
[..],
1018 |s
, ty
| s
.print_type(ty
))?
;
1019 if elts
.len() == 1 {
1024 ast
::TyKind
::Paren(ref typ
) => {
1026 self.print_type(typ
)?
;
1029 ast
::TyKind
::BareFn(ref f
) => {
1030 let generics
= ast
::Generics
{
1031 lifetimes
: f
.lifetimes
.clone(),
1032 ty_params
: Vec
::new(),
1033 where_clause
: ast
::WhereClause
{
1034 id
: ast
::DUMMY_NODE_ID
,
1035 predicates
: Vec
::new(),
1036 span
: syntax_pos
::DUMMY_SP
,
1038 span
: syntax_pos
::DUMMY_SP
,
1040 self.print_ty_fn(f
.abi
,
1046 ast
::TyKind
::Path(None
, ref path
) => {
1047 self.print_path(path
, false, 0, false)?
;
1049 ast
::TyKind
::Path(Some(ref qself
), ref path
) => {
1050 self.print_qpath(path
, qself
, false)?
1052 ast
::TyKind
::TraitObject(ref bounds
) => {
1053 self.print_bounds("", &bounds
[..])?
;
1055 ast
::TyKind
::ImplTrait(ref bounds
) => {
1056 self.print_bounds("impl ", &bounds
[..])?
;
1058 ast
::TyKind
::Array(ref ty
, ref v
) => {
1060 self.print_type(ty
)?
;
1062 self.print_expr(v
)?
;
1065 ast
::TyKind
::Typeof(ref e
) => {
1066 self.s
.word("typeof(")?
;
1067 self.print_expr(e
)?
;
1070 ast
::TyKind
::Infer
=> {
1073 ast
::TyKind
::Err
=> {
1076 ast
::TyKind
::ImplicitSelf
=> {
1077 self.s
.word("Self")?
;
1079 ast
::TyKind
::Mac(ref m
) => {
1080 self.print_mac(m
, token
::Paren
)?
;
1086 pub fn print_foreign_item(&mut self,
1087 item
: &ast
::ForeignItem
) -> io
::Result
<()> {
1088 self.hardbreak_if_not_bol()?
;
1089 self.maybe_print_comment(item
.span
.lo())?
;
1090 self.print_outer_attributes(&item
.attrs
)?
;
1092 ast
::ForeignItemKind
::Fn(ref decl
, ref generics
) => {
1094 self.print_fn(decl
, ast
::Unsafety
::Normal
,
1095 ast
::Constness
::NotConst
,
1096 Abi
::Rust
, Some(item
.ident
),
1097 generics
, &item
.vis
)?
;
1098 self.end()?
; // end head-ibox
1100 self.end() // end the outer fn box
1102 ast
::ForeignItemKind
::Static(ref t
, m
) => {
1103 self.head(&visibility_qualified(&item
.vis
, "static"))?
;
1105 self.word_space("mut")?
;
1107 self.print_ident(item
.ident
)?
;
1108 self.word_space(":")?
;
1109 self.print_type(t
)?
;
1111 self.end()?
; // end the head-ibox
1112 self.end() // end the outer cbox
1117 fn print_associated_const(&mut self,
1120 default: Option
<&ast
::Expr
>,
1121 vis
: &ast
::Visibility
)
1124 self.s
.word(&visibility_qualified(vis
, ""))?
;
1125 self.word_space("const")?
;
1126 self.print_ident(ident
)?
;
1127 self.word_space(":")?
;
1128 self.print_type(ty
)?
;
1129 if let Some(expr
) = default {
1131 self.word_space("=")?
;
1132 self.print_expr(expr
)?
;
1137 fn print_associated_type(&mut self,
1139 bounds
: Option
<&ast
::TyParamBounds
>,
1140 ty
: Option
<&ast
::Ty
>)
1142 self.word_space("type")?
;
1143 self.print_ident(ident
)?
;
1144 if let Some(bounds
) = bounds
{
1145 self.print_bounds(":", bounds
)?
;
1147 if let Some(ty
) = ty
{
1149 self.word_space("=")?
;
1150 self.print_type(ty
)?
;
1155 /// Pretty-print an item
1156 pub fn print_item(&mut self, item
: &ast
::Item
) -> io
::Result
<()> {
1157 self.hardbreak_if_not_bol()?
;
1158 self.maybe_print_comment(item
.span
.lo())?
;
1159 self.print_outer_attributes(&item
.attrs
)?
;
1160 self.ann
.pre(self, NodeItem(item
))?
;
1162 ast
::ItemKind
::ExternCrate(ref optional_path
) => {
1163 self.head(&visibility_qualified(&item
.vis
, "extern crate"))?
;
1164 if let Some(p
) = *optional_path
{
1165 let val
= p
.as_str();
1166 if val
.contains('
-'
) {
1167 self.print_string(&val
, ast
::StrStyle
::Cooked
)?
;
1169 self.print_name(p
)?
;
1175 self.print_ident(item
.ident
)?
;
1177 self.end()?
; // end inner head-block
1178 self.end()?
; // end outer head-block
1180 ast
::ItemKind
::Use(ref vp
) => {
1181 self.head(&visibility_qualified(&item
.vis
, "use"))?
;
1182 self.print_view_path(vp
)?
;
1184 self.end()?
; // end inner head-block
1185 self.end()?
; // end outer head-block
1187 ast
::ItemKind
::Static(ref ty
, m
, ref expr
) => {
1188 self.head(&visibility_qualified(&item
.vis
, "static"))?
;
1189 if m
== ast
::Mutability
::Mutable
{
1190 self.word_space("mut")?
;
1192 self.print_ident(item
.ident
)?
;
1193 self.word_space(":")?
;
1194 self.print_type(ty
)?
;
1196 self.end()?
; // end the head-ibox
1198 self.word_space("=")?
;
1199 self.print_expr(expr
)?
;
1201 self.end()?
; // end the outer cbox
1203 ast
::ItemKind
::Const(ref ty
, ref expr
) => {
1204 self.head(&visibility_qualified(&item
.vis
, "const"))?
;
1205 self.print_ident(item
.ident
)?
;
1206 self.word_space(":")?
;
1207 self.print_type(ty
)?
;
1209 self.end()?
; // end the head-ibox
1211 self.word_space("=")?
;
1212 self.print_expr(expr
)?
;
1214 self.end()?
; // end the outer cbox
1216 ast
::ItemKind
::Fn(ref decl
, unsafety
, constness
, abi
, ref typarams
, ref body
) => {
1228 self.print_block_with_attrs(body
, &item
.attrs
)?
;
1230 ast
::ItemKind
::Mod(ref _mod
) => {
1231 self.head(&visibility_qualified(&item
.vis
, "mod"))?
;
1232 self.print_ident(item
.ident
)?
;
1235 self.print_mod(_mod
, &item
.attrs
)?
;
1236 self.bclose(item
.span
)?
;
1238 ast
::ItemKind
::ForeignMod(ref nmod
) => {
1239 self.head("extern")?
;
1240 self.word_nbsp(&nmod
.abi
.to_string())?
;
1242 self.print_foreign_mod(nmod
, &item
.attrs
)?
;
1243 self.bclose(item
.span
)?
;
1245 ast
::ItemKind
::GlobalAsm(ref ga
) => {
1246 self.head(&visibility_qualified(&item
.vis
, "global_asm!"))?
;
1247 self.s
.word(&ga
.asm
.as_str())?
;
1250 ast
::ItemKind
::Ty(ref ty
, ref params
) => {
1251 self.ibox(INDENT_UNIT
)?
;
1253 self.word_nbsp(&visibility_qualified(&item
.vis
, "type"))?
;
1254 self.print_ident(item
.ident
)?
;
1255 self.print_generics(params
)?
;
1256 self.end()?
; // end the inner ibox
1258 self.print_where_clause(¶ms
.where_clause
)?
;
1260 self.word_space("=")?
;
1261 self.print_type(ty
)?
;
1263 self.end()?
; // end the outer ibox
1265 ast
::ItemKind
::Enum(ref enum_definition
, ref params
) => {
1266 self.print_enum_def(
1274 ast
::ItemKind
::Struct(ref struct_def
, ref generics
) => {
1275 self.head(&visibility_qualified(&item
.vis
, "struct"))?
;
1276 self.print_struct(struct_def
, generics
, item
.ident
, item
.span
, true)?
;
1278 ast
::ItemKind
::Union(ref struct_def
, ref generics
) => {
1279 self.head(&visibility_qualified(&item
.vis
, "union"))?
;
1280 self.print_struct(struct_def
, generics
, item
.ident
, item
.span
, true)?
;
1282 ast
::ItemKind
::DefaultImpl(unsafety
, ref trait_ref
) => {
1284 self.print_visibility(&item
.vis
)?
;
1285 self.print_unsafety(unsafety
)?
;
1286 self.word_nbsp("impl")?
;
1287 self.print_trait_ref(trait_ref
)?
;
1289 self.word_space("for")?
;
1290 self.word_space("..")?
;
1292 self.bclose(item
.span
)?
;
1294 ast
::ItemKind
::Impl(unsafety
,
1300 ref impl_items
) => {
1302 self.print_visibility(&item
.vis
)?
;
1303 self.print_defaultness(defaultness
)?
;
1304 self.print_unsafety(unsafety
)?
;
1305 self.word_nbsp("impl")?
;
1307 if generics
.is_parameterized() {
1308 self.print_generics(generics
)?
;
1312 if polarity
== ast
::ImplPolarity
::Negative
{
1316 if let Some(ref t
) = *opt_trait
{
1317 self.print_trait_ref(t
)?
;
1319 self.word_space("for")?
;
1322 self.print_type(ty
)?
;
1323 self.print_where_clause(&generics
.where_clause
)?
;
1327 self.print_inner_attributes(&item
.attrs
)?
;
1328 for impl_item
in impl_items
{
1329 self.print_impl_item(impl_item
)?
;
1331 self.bclose(item
.span
)?
;
1333 ast
::ItemKind
::Trait(unsafety
, ref generics
, ref bounds
, ref trait_items
) => {
1335 self.print_visibility(&item
.vis
)?
;
1336 self.print_unsafety(unsafety
)?
;
1337 self.word_nbsp("trait")?
;
1338 self.print_ident(item
.ident
)?
;
1339 self.print_generics(generics
)?
;
1340 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
1341 for b
in bounds
.iter() {
1342 if let TraitTyParamBound(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = *b
{
1344 self.word_space("for ?")?
;
1345 self.print_trait_ref(&ptr
.trait_ref
)?
;
1347 real_bounds
.push(b
.clone());
1350 self.print_bounds(":", &real_bounds
[..])?
;
1351 self.print_where_clause(&generics
.where_clause
)?
;
1354 for trait_item
in trait_items
{
1355 self.print_trait_item(trait_item
)?
;
1357 self.bclose(item
.span
)?
;
1359 ast
::ItemKind
::Mac(codemap
::Spanned { ref node, .. }
) => {
1360 self.print_path(&node
.path
, false, 0, false)?
;
1362 self.print_ident(item
.ident
)?
;
1363 self.cbox(INDENT_UNIT
)?
;
1365 self.print_tts(node
.stream())?
;
1370 ast
::ItemKind
::MacroDef(ref tts
) => {
1371 self.s
.word("macro_rules! ")?
;
1372 self.print_ident(item
.ident
)?
;
1373 self.cbox(INDENT_UNIT
)?
;
1375 self.print_tts(tts
.stream())?
;
1381 self.ann
.post(self, NodeItem(item
))
1384 fn print_trait_ref(&mut self, t
: &ast
::TraitRef
) -> io
::Result
<()> {
1385 self.print_path(&t
.path
, false, 0, false)
1388 fn print_formal_lifetime_list(&mut self, lifetimes
: &[ast
::LifetimeDef
]) -> io
::Result
<()> {
1389 if !lifetimes
.is_empty() {
1390 self.s
.word("for<")?
;
1391 let mut comma
= false;
1392 for lifetime_def
in lifetimes
{
1394 self.word_space(",")?
1396 self.print_outer_attributes_inline(&lifetime_def
.attrs
)?
;
1397 self.print_lifetime_bounds(&lifetime_def
.lifetime
, &lifetime_def
.bounds
)?
;
1405 fn print_poly_trait_ref(&mut self, t
: &ast
::PolyTraitRef
) -> io
::Result
<()> {
1406 self.print_formal_lifetime_list(&t
.bound_lifetimes
)?
;
1407 self.print_trait_ref(&t
.trait_ref
)
1410 pub fn print_enum_def(&mut self, enum_definition
: &ast
::EnumDef
,
1411 generics
: &ast
::Generics
, ident
: ast
::Ident
,
1412 span
: syntax_pos
::Span
,
1413 visibility
: &ast
::Visibility
) -> io
::Result
<()> {
1414 self.head(&visibility_qualified(visibility
, "enum"))?
;
1415 self.print_ident(ident
)?
;
1416 self.print_generics(generics
)?
;
1417 self.print_where_clause(&generics
.where_clause
)?
;
1419 self.print_variants(&enum_definition
.variants
, span
)
1422 pub fn print_variants(&mut self,
1423 variants
: &[ast
::Variant
],
1424 span
: syntax_pos
::Span
) -> io
::Result
<()> {
1427 self.space_if_not_bol()?
;
1428 self.maybe_print_comment(v
.span
.lo())?
;
1429 self.print_outer_attributes(&v
.node
.attrs
)?
;
1430 self.ibox(INDENT_UNIT
)?
;
1431 self.print_variant(v
)?
;
1434 self.maybe_print_trailing_comment(v
.span
, None
)?
;
1439 pub fn print_visibility(&mut self, vis
: &ast
::Visibility
) -> io
::Result
<()> {
1441 ast
::Visibility
::Public
=> self.word_nbsp("pub"),
1442 ast
::Visibility
::Crate(_
) => self.word_nbsp("pub(crate)"),
1443 ast
::Visibility
::Restricted { ref path, .. }
=> {
1444 let path
= to_string(|s
| s
.print_path(path
, false, 0, true));
1445 if path
== "self" || path
== "super" {
1446 self.word_nbsp(&format
!("pub({})", path
))
1448 self.word_nbsp(&format
!("pub(in {})", path
))
1451 ast
::Visibility
::Inherited
=> Ok(())
1455 pub fn print_defaultness(&mut self, defatulness
: ast
::Defaultness
) -> io
::Result
<()> {
1456 if let ast
::Defaultness
::Default
= defatulness
{
1457 try
!(self.word_nbsp("default"));
1462 pub fn print_struct(&mut self,
1463 struct_def
: &ast
::VariantData
,
1464 generics
: &ast
::Generics
,
1466 span
: syntax_pos
::Span
,
1467 print_finalizer
: bool
) -> io
::Result
<()> {
1468 self.print_ident(ident
)?
;
1469 self.print_generics(generics
)?
;
1470 if !struct_def
.is_struct() {
1471 if struct_def
.is_tuple() {
1474 Inconsistent
, struct_def
.fields(),
1476 s
.maybe_print_comment(field
.span
.lo())?
;
1477 s
.print_outer_attributes(&field
.attrs
)?
;
1478 s
.print_visibility(&field
.vis
)?
;
1479 s
.print_type(&field
.ty
)
1484 self.print_where_clause(&generics
.where_clause
)?
;
1485 if print_finalizer
{
1489 self.end() // close the outer-box
1491 self.print_where_clause(&generics
.where_clause
)?
;
1494 self.hardbreak_if_not_bol()?
;
1496 for field
in struct_def
.fields() {
1497 self.hardbreak_if_not_bol()?
;
1498 self.maybe_print_comment(field
.span
.lo())?
;
1499 self.print_outer_attributes(&field
.attrs
)?
;
1500 self.print_visibility(&field
.vis
)?
;
1501 self.print_ident(field
.ident
.unwrap())?
;
1502 self.word_nbsp(":")?
;
1503 self.print_type(&field
.ty
)?
;
1511 pub fn print_variant(&mut self, v
: &ast
::Variant
) -> io
::Result
<()> {
1513 let generics
= ast
::Generics
::default();
1514 self.print_struct(&v
.node
.data
, &generics
, v
.node
.name
, v
.span
, false)?
;
1515 match v
.node
.disr_expr
{
1518 self.word_space("=")?
;
1525 pub fn print_method_sig(&mut self,
1528 vis
: &ast
::Visibility
)
1530 self.print_fn(&m
.decl
,
1539 pub fn print_trait_item(&mut self, ti
: &ast
::TraitItem
)
1541 self.ann
.pre(self, NodeSubItem(ti
.id
))?
;
1542 self.hardbreak_if_not_bol()?
;
1543 self.maybe_print_comment(ti
.span
.lo())?
;
1544 self.print_outer_attributes(&ti
.attrs
)?
;
1546 ast
::TraitItemKind
::Const(ref ty
, ref default) => {
1547 self.print_associated_const(ti
.ident
, ty
,
1548 default.as_ref().map(|expr
| &**expr
),
1549 &ast
::Visibility
::Inherited
)?
;
1551 ast
::TraitItemKind
::Method(ref sig
, ref body
) => {
1555 self.print_method_sig(ti
.ident
, sig
, &ast
::Visibility
::Inherited
)?
;
1556 if let Some(ref body
) = *body
{
1558 self.print_block_with_attrs(body
, &ti
.attrs
)?
;
1563 ast
::TraitItemKind
::Type(ref bounds
, ref default) => {
1564 self.print_associated_type(ti
.ident
, Some(bounds
),
1565 default.as_ref().map(|ty
| &**ty
))?
;
1567 ast
::TraitItemKind
::Macro(codemap
::Spanned { ref node, .. }
) => {
1568 // code copied from ItemKind::Mac:
1569 self.print_path(&node
.path
, false, 0, false)?
;
1571 self.cbox(INDENT_UNIT
)?
;
1573 self.print_tts(node
.stream())?
;
1579 self.ann
.post(self, NodeSubItem(ti
.id
))
1582 pub fn print_impl_item(&mut self, ii
: &ast
::ImplItem
) -> io
::Result
<()> {
1583 self.ann
.pre(self, NodeSubItem(ii
.id
))?
;
1584 self.hardbreak_if_not_bol()?
;
1585 self.maybe_print_comment(ii
.span
.lo())?
;
1586 self.print_outer_attributes(&ii
.attrs
)?
;
1587 self.print_defaultness(ii
.defaultness
)?
;
1589 ast
::ImplItemKind
::Const(ref ty
, ref expr
) => {
1590 self.print_associated_const(ii
.ident
, ty
, Some(expr
), &ii
.vis
)?
;
1592 ast
::ImplItemKind
::Method(ref sig
, ref body
) => {
1594 self.print_method_sig(ii
.ident
, sig
, &ii
.vis
)?
;
1596 self.print_block_with_attrs(body
, &ii
.attrs
)?
;
1598 ast
::ImplItemKind
::Type(ref ty
) => {
1599 self.print_associated_type(ii
.ident
, None
, Some(ty
))?
;
1601 ast
::ImplItemKind
::Macro(codemap
::Spanned { ref node, .. }
) => {
1602 // code copied from ItemKind::Mac:
1603 self.print_path(&node
.path
, false, 0, false)?
;
1605 self.cbox(INDENT_UNIT
)?
;
1607 self.print_tts(node
.stream())?
;
1613 self.ann
.post(self, NodeSubItem(ii
.id
))
1616 pub fn print_stmt(&mut self, st
: &ast
::Stmt
) -> io
::Result
<()> {
1617 self.maybe_print_comment(st
.span
.lo())?
;
1619 ast
::StmtKind
::Local(ref loc
) => {
1620 self.print_outer_attributes(&loc
.attrs
)?
;
1621 self.space_if_not_bol()?
;
1622 self.ibox(INDENT_UNIT
)?
;
1623 self.word_nbsp("let")?
;
1625 self.ibox(INDENT_UNIT
)?
;
1626 self.print_local_decl(loc
)?
;
1628 if let Some(ref init
) = loc
.init
{
1630 self.word_space("=")?
;
1631 self.print_expr(init
)?
;
1636 ast
::StmtKind
::Item(ref item
) => self.print_item(item
)?
,
1637 ast
::StmtKind
::Expr(ref expr
) => {
1638 self.space_if_not_bol()?
;
1639 self.print_expr_outer_attr_style(expr
, false)?
;
1640 if parse
::classify
::expr_requires_semi_to_be_stmt(expr
) {
1644 ast
::StmtKind
::Semi(ref expr
) => {
1645 self.space_if_not_bol()?
;
1646 self.print_expr_outer_attr_style(expr
, false)?
;
1649 ast
::StmtKind
::Mac(ref mac
) => {
1650 let (ref mac
, style
, ref attrs
) = **mac
;
1651 self.space_if_not_bol()?
;
1652 self.print_outer_attributes(attrs
)?
;
1653 let delim
= match style
{
1654 ast
::MacStmtStyle
::Braces
=> token
::Brace
,
1657 self.print_mac(mac
, delim
)?
;
1658 if style
== ast
::MacStmtStyle
::Semicolon
{
1663 self.maybe_print_trailing_comment(st
.span
, None
)
1666 pub fn print_block(&mut self, blk
: &ast
::Block
) -> io
::Result
<()> {
1667 self.print_block_with_attrs(blk
, &[])
1670 pub fn print_block_unclosed(&mut self, blk
: &ast
::Block
) -> io
::Result
<()> {
1671 self.print_block_unclosed_indent(blk
, INDENT_UNIT
)
1674 pub fn print_block_unclosed_with_attrs(&mut self, blk
: &ast
::Block
,
1675 attrs
: &[ast
::Attribute
])
1677 self.print_block_maybe_unclosed(blk
, INDENT_UNIT
, attrs
, false)
1680 pub fn print_block_unclosed_indent(&mut self, blk
: &ast
::Block
,
1681 indented
: usize) -> io
::Result
<()> {
1682 self.print_block_maybe_unclosed(blk
, indented
, &[], false)
1685 pub fn print_block_with_attrs(&mut self,
1687 attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
1688 self.print_block_maybe_unclosed(blk
, INDENT_UNIT
, attrs
, true)
1691 pub fn print_block_maybe_unclosed(&mut self,
1694 attrs
: &[ast
::Attribute
],
1695 close_box
: bool
) -> io
::Result
<()> {
1697 BlockCheckMode
::Unsafe(..) => self.word_space("unsafe")?
,
1698 BlockCheckMode
::Default
=> ()
1700 self.maybe_print_comment(blk
.span
.lo())?
;
1701 self.ann
.pre(self, NodeBlock(blk
))?
;
1704 self.print_inner_attributes(attrs
)?
;
1706 for (i
, st
) in blk
.stmts
.iter().enumerate() {
1708 ast
::StmtKind
::Expr(ref expr
) if i
== blk
.stmts
.len() - 1 => {
1709 self.maybe_print_comment(st
.span
.lo())?
;
1710 self.space_if_not_bol()?
;
1711 self.print_expr_outer_attr_style(expr
, false)?
;
1712 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()))?
;
1714 _
=> self.print_stmt(st
)?
,
1718 self.bclose_maybe_open(blk
.span
, indented
, close_box
)?
;
1719 self.ann
.post(self, NodeBlock(blk
))
1722 fn print_else(&mut self, els
: Option
<&ast
::Expr
>) -> io
::Result
<()> {
1726 // "another else-if"
1727 ast
::ExprKind
::If(ref i
, ref then
, ref e
) => {
1728 self.cbox(INDENT_UNIT
- 1)?
;
1730 self.s
.word(" else if ")?
;
1731 self.print_expr_as_cond(i
)?
;
1733 self.print_block(then
)?
;
1734 self.print_else(e
.as_ref().map(|e
| &**e
))
1736 // "another else-if-let"
1737 ast
::ExprKind
::IfLet(ref pat
, ref expr
, ref then
, ref e
) => {
1738 self.cbox(INDENT_UNIT
- 1)?
;
1740 self.s
.word(" else if let ")?
;
1741 self.print_pat(pat
)?
;
1743 self.word_space("=")?
;
1744 self.print_expr_as_cond(expr
)?
;
1746 self.print_block(then
)?
;
1747 self.print_else(e
.as_ref().map(|e
| &**e
))
1750 ast
::ExprKind
::Block(ref b
) => {
1751 self.cbox(INDENT_UNIT
- 1)?
;
1753 self.s
.word(" else ")?
;
1756 // BLEAH, constraints would be great here
1758 panic
!("print_if saw if with weird alternative");
1766 pub fn print_if(&mut self, test
: &ast
::Expr
, blk
: &ast
::Block
,
1767 elseopt
: Option
<&ast
::Expr
>) -> io
::Result
<()> {
1769 self.print_expr_as_cond(test
)?
;
1771 self.print_block(blk
)?
;
1772 self.print_else(elseopt
)
1775 pub fn print_if_let(&mut self, pat
: &ast
::Pat
, expr
: &ast
::Expr
, blk
: &ast
::Block
,
1776 elseopt
: Option
<&ast
::Expr
>) -> io
::Result
<()> {
1777 self.head("if let")?
;
1778 self.print_pat(pat
)?
;
1780 self.word_space("=")?
;
1781 self.print_expr_as_cond(expr
)?
;
1783 self.print_block(blk
)?
;
1784 self.print_else(elseopt
)
1787 pub fn print_mac(&mut self, m
: &ast
::Mac
, delim
: token
::DelimToken
)
1789 self.print_path(&m
.node
.path
, false, 0, false)?
;
1792 token
::Paren
=> self.popen()?
,
1793 token
::Bracket
=> self.s
.word("[")?
,
1798 token
::NoDelim
=> {}
1800 self.print_tts(m
.node
.stream())?
;
1802 token
::Paren
=> self.pclose(),
1803 token
::Bracket
=> self.s
.word("]"),
1804 token
::Brace
=> self.bclose(m
.span
),
1805 token
::NoDelim
=> Ok(()),
1810 fn print_call_post(&mut self, args
: &[P
<ast
::Expr
>]) -> io
::Result
<()> {
1812 self.commasep_exprs(Inconsistent
, args
)?
;
1816 pub fn print_expr_maybe_paren(&mut self, expr
: &ast
::Expr
, prec
: i8) -> io
::Result
<()> {
1817 let needs_par
= parser
::expr_precedence(expr
) < prec
;
1821 self.print_expr(expr
)?
;
1828 /// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
1829 /// `if cond { ... }`.
1830 pub fn print_expr_as_cond(&mut self, expr
: &ast
::Expr
) -> io
::Result
<()> {
1831 let needs_par
= match expr
.node
{
1832 // These cases need parens due to the parse error observed in #26461: `if return {}`
1833 // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1834 ast
::ExprKind
::Closure(..) |
1835 ast
::ExprKind
::Ret(..) |
1836 ast
::ExprKind
::Break(..) => true,
1838 _
=> parser
::contains_exterior_struct_lit(expr
),
1844 self.print_expr(expr
)?
;
1851 fn print_expr_in_place(&mut self,
1853 expr
: &ast
::Expr
) -> io
::Result
<()> {
1854 let prec
= AssocOp
::Inplace
.precedence() as i8;
1855 self.print_expr_maybe_paren(place
, prec
+ 1)?
;
1857 self.word_space("<-")?
;
1858 self.print_expr_maybe_paren(expr
, prec
)
1861 fn print_expr_vec(&mut self, exprs
: &[P
<ast
::Expr
>],
1862 attrs
: &[Attribute
]) -> io
::Result
<()> {
1863 self.ibox(INDENT_UNIT
)?
;
1865 self.print_inner_attributes_inline(attrs
)?
;
1866 self.commasep_exprs(Inconsistent
, &exprs
[..])?
;
1871 fn print_expr_repeat(&mut self,
1872 element
: &ast
::Expr
,
1874 attrs
: &[Attribute
]) -> io
::Result
<()> {
1875 self.ibox(INDENT_UNIT
)?
;
1877 self.print_inner_attributes_inline(attrs
)?
;
1878 self.print_expr(element
)?
;
1879 self.word_space(";")?
;
1880 self.print_expr(count
)?
;
1885 fn print_expr_struct(&mut self,
1887 fields
: &[ast
::Field
],
1888 wth
: &Option
<P
<ast
::Expr
>>,
1889 attrs
: &[Attribute
]) -> io
::Result
<()> {
1890 self.print_path(path
, true, 0, false)?
;
1892 self.print_inner_attributes_inline(attrs
)?
;
1897 s
.ibox(INDENT_UNIT
)?
;
1898 if !field
.is_shorthand
{
1899 s
.print_ident(field
.ident
.node
)?
;
1902 s
.print_expr(&field
.expr
)?
;
1908 self.ibox(INDENT_UNIT
)?
;
1909 if !fields
.is_empty() {
1914 self.print_expr(expr
)?
;
1917 _
=> if !fields
.is_empty() {
1925 fn print_expr_tup(&mut self, exprs
: &[P
<ast
::Expr
>],
1926 attrs
: &[Attribute
]) -> io
::Result
<()> {
1928 self.print_inner_attributes_inline(attrs
)?
;
1929 self.commasep_exprs(Inconsistent
, &exprs
[..])?
;
1930 if exprs
.len() == 1 {
1936 fn print_expr_call(&mut self,
1938 args
: &[P
<ast
::Expr
>]) -> io
::Result
<()> {
1941 ast
::ExprKind
::Field(..) |
1942 ast
::ExprKind
::TupField(..) => parser
::PREC_FORCE_PAREN
,
1943 _
=> parser
::PREC_POSTFIX
,
1946 self.print_expr_maybe_paren(func
, prec
)?
;
1947 self.print_call_post(args
)
1950 fn print_expr_method_call(&mut self,
1951 segment
: &ast
::PathSegment
,
1952 args
: &[P
<ast
::Expr
>]) -> io
::Result
<()> {
1953 let base_args
= &args
[1..];
1954 self.print_expr_maybe_paren(&args
[0], parser
::PREC_POSTFIX
)?
;
1956 self.print_ident(segment
.identifier
)?
;
1957 if let Some(ref parameters
) = segment
.parameters
{
1958 self.print_path_parameters(parameters
, true)?
;
1960 self.print_call_post(base_args
)
1963 fn print_expr_binary(&mut self,
1966 rhs
: &ast
::Expr
) -> io
::Result
<()> {
1967 let assoc_op
= AssocOp
::from_ast_binop(op
.node
);
1968 let prec
= assoc_op
.precedence() as i8;
1969 let fixity
= assoc_op
.fixity();
1971 let (left_prec
, right_prec
) = match fixity
{
1972 Fixity
::Left
=> (prec
, prec
+ 1),
1973 Fixity
::Right
=> (prec
+ 1, prec
),
1974 Fixity
::None
=> (prec
+ 1, prec
+ 1),
1977 self.print_expr_maybe_paren(lhs
, left_prec
)?
;
1979 self.word_space(op
.node
.to_string())?
;
1980 self.print_expr_maybe_paren(rhs
, right_prec
)
1983 fn print_expr_unary(&mut self,
1985 expr
: &ast
::Expr
) -> io
::Result
<()> {
1986 self.s
.word(ast
::UnOp
::to_string(op
))?
;
1987 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1990 fn print_expr_addr_of(&mut self,
1991 mutability
: ast
::Mutability
,
1992 expr
: &ast
::Expr
) -> io
::Result
<()> {
1994 self.print_mutability(mutability
)?
;
1995 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1998 pub fn print_expr(&mut self, expr
: &ast
::Expr
) -> io
::Result
<()> {
1999 self.print_expr_outer_attr_style(expr
, true)
2002 fn print_expr_outer_attr_style(&mut self,
2004 is_inline
: bool
) -> io
::Result
<()> {
2005 self.maybe_print_comment(expr
.span
.lo())?
;
2007 let attrs
= &expr
.attrs
;
2009 self.print_outer_attributes_inline(attrs
)?
;
2011 self.print_outer_attributes(attrs
)?
;
2014 self.ibox(INDENT_UNIT
)?
;
2015 self.ann
.pre(self, NodeExpr(expr
))?
;
2017 ast
::ExprKind
::Box(ref expr
) => {
2018 self.word_space("box")?
;
2019 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)?
;
2021 ast
::ExprKind
::InPlace(ref place
, ref expr
) => {
2022 self.print_expr_in_place(place
, expr
)?
;
2024 ast
::ExprKind
::Array(ref exprs
) => {
2025 self.print_expr_vec(&exprs
[..], attrs
)?
;
2027 ast
::ExprKind
::Repeat(ref element
, ref count
) => {
2028 self.print_expr_repeat(element
, count
, attrs
)?
;
2030 ast
::ExprKind
::Struct(ref path
, ref fields
, ref wth
) => {
2031 self.print_expr_struct(path
, &fields
[..], wth
, attrs
)?
;
2033 ast
::ExprKind
::Tup(ref exprs
) => {
2034 self.print_expr_tup(&exprs
[..], attrs
)?
;
2036 ast
::ExprKind
::Call(ref func
, ref args
) => {
2037 self.print_expr_call(func
, &args
[..])?
;
2039 ast
::ExprKind
::MethodCall(ref segment
, ref args
) => {
2040 self.print_expr_method_call(segment
, &args
[..])?
;
2042 ast
::ExprKind
::Binary(op
, ref lhs
, ref rhs
) => {
2043 self.print_expr_binary(op
, lhs
, rhs
)?
;
2045 ast
::ExprKind
::Unary(op
, ref expr
) => {
2046 self.print_expr_unary(op
, expr
)?
;
2048 ast
::ExprKind
::AddrOf(m
, ref expr
) => {
2049 self.print_expr_addr_of(m
, expr
)?
;
2051 ast
::ExprKind
::Lit(ref lit
) => {
2052 self.print_literal(lit
)?
;
2054 ast
::ExprKind
::Cast(ref expr
, ref ty
) => {
2055 let prec
= AssocOp
::As
.precedence() as i8;
2056 self.print_expr_maybe_paren(expr
, prec
)?
;
2058 self.word_space("as")?
;
2059 self.print_type(ty
)?
;
2061 ast
::ExprKind
::Type(ref expr
, ref ty
) => {
2062 let prec
= AssocOp
::Colon
.precedence() as i8;
2063 self.print_expr_maybe_paren(expr
, prec
)?
;
2064 self.word_space(":")?
;
2065 self.print_type(ty
)?
;
2067 ast
::ExprKind
::If(ref test
, ref blk
, ref elseopt
) => {
2068 self.print_if(test
, blk
, elseopt
.as_ref().map(|e
| &**e
))?
;
2070 ast
::ExprKind
::IfLet(ref pat
, ref expr
, ref blk
, ref elseopt
) => {
2071 self.print_if_let(pat
, expr
, blk
, elseopt
.as_ref().map(|e
| &**e
))?
;
2073 ast
::ExprKind
::While(ref test
, ref blk
, opt_ident
) => {
2074 if let Some(ident
) = opt_ident
{
2075 self.print_ident(ident
.node
)?
;
2076 self.word_space(":")?
;
2078 self.head("while")?
;
2079 self.print_expr_as_cond(test
)?
;
2081 self.print_block_with_attrs(blk
, attrs
)?
;
2083 ast
::ExprKind
::WhileLet(ref pat
, ref expr
, ref blk
, opt_ident
) => {
2084 if let Some(ident
) = opt_ident
{
2085 self.print_ident(ident
.node
)?
;
2086 self.word_space(":")?
;
2088 self.head("while let")?
;
2089 self.print_pat(pat
)?
;
2091 self.word_space("=")?
;
2092 self.print_expr_as_cond(expr
)?
;
2094 self.print_block_with_attrs(blk
, attrs
)?
;
2096 ast
::ExprKind
::ForLoop(ref pat
, ref iter
, ref blk
, opt_ident
) => {
2097 if let Some(ident
) = opt_ident
{
2098 self.print_ident(ident
.node
)?
;
2099 self.word_space(":")?
;
2102 self.print_pat(pat
)?
;
2104 self.word_space("in")?
;
2105 self.print_expr_as_cond(iter
)?
;
2107 self.print_block_with_attrs(blk
, attrs
)?
;
2109 ast
::ExprKind
::Loop(ref blk
, opt_ident
) => {
2110 if let Some(ident
) = opt_ident
{
2111 self.print_ident(ident
.node
)?
;
2112 self.word_space(":")?
;
2116 self.print_block_with_attrs(blk
, attrs
)?
;
2118 ast
::ExprKind
::Match(ref expr
, ref arms
) => {
2119 self.cbox(INDENT_UNIT
)?
;
2121 self.word_nbsp("match")?
;
2122 self.print_expr_as_cond(expr
)?
;
2125 self.print_inner_attributes_no_trailing_hardbreak(attrs
)?
;
2127 self.print_arm(arm
)?
;
2129 self.bclose_(expr
.span
, INDENT_UNIT
)?
;
2131 ast
::ExprKind
::Closure(capture_clause
, ref decl
, ref body
, _
) => {
2132 self.print_capture_clause(capture_clause
)?
;
2134 self.print_fn_block_args(decl
)?
;
2136 self.print_expr(body
)?
;
2137 self.end()?
; // need to close a box
2139 // a box will be closed by print_expr, but we didn't want an overall
2140 // wrapper so we closed the corresponding opening. so create an
2141 // empty box to satisfy the close.
2144 ast
::ExprKind
::Block(ref blk
) => {
2145 // containing cbox, will be closed by print-block at }
2146 self.cbox(INDENT_UNIT
)?
;
2147 // head-box, will be closed by print-block after {
2149 self.print_block_with_attrs(blk
, attrs
)?
;
2151 ast
::ExprKind
::Assign(ref lhs
, ref rhs
) => {
2152 let prec
= AssocOp
::Assign
.precedence() as i8;
2153 self.print_expr_maybe_paren(lhs
, prec
+ 1)?
;
2155 self.word_space("=")?
;
2156 self.print_expr_maybe_paren(rhs
, prec
)?
;
2158 ast
::ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => {
2159 let prec
= AssocOp
::Assign
.precedence() as i8;
2160 self.print_expr_maybe_paren(lhs
, prec
+ 1)?
;
2162 self.s
.word(op
.node
.to_string())?
;
2163 self.word_space("=")?
;
2164 self.print_expr_maybe_paren(rhs
, prec
)?
;
2166 ast
::ExprKind
::Field(ref expr
, id
) => {
2167 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
)?
;
2169 self.print_ident(id
.node
)?
;
2171 ast
::ExprKind
::TupField(ref expr
, id
) => {
2172 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
)?
;
2174 self.print_usize(id
.node
)?
;
2176 ast
::ExprKind
::Index(ref expr
, ref index
) => {
2177 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
)?
;
2179 self.print_expr(index
)?
;
2182 ast
::ExprKind
::Range(ref start
, ref end
, limits
) => {
2183 // Special case for `Range`. `AssocOp` claims that `Range` has higher precedence
2184 // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
2185 // Here we use a fake precedence value so that any child with lower precedence than
2186 // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
2187 let fake_prec
= AssocOp
::LOr
.precedence() as i8;
2188 if let Some(ref e
) = *start
{
2189 self.print_expr_maybe_paren(e
, fake_prec
)?
;
2191 if limits
== ast
::RangeLimits
::HalfOpen
{
2194 self.s
.word("...")?
;
2196 if let Some(ref e
) = *end
{
2197 self.print_expr_maybe_paren(e
, fake_prec
)?
;
2200 ast
::ExprKind
::Path(None
, ref path
) => {
2201 self.print_path(path
, true, 0, false)?
2203 ast
::ExprKind
::Path(Some(ref qself
), ref path
) => {
2204 self.print_qpath(path
, qself
, true)?
2206 ast
::ExprKind
::Break(opt_ident
, ref opt_expr
) => {
2207 self.s
.word("break")?
;
2209 if let Some(ident
) = opt_ident
{
2210 self.print_ident(ident
.node
)?
;
2213 if let Some(ref expr
) = *opt_expr
{
2214 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
)?
;
2218 ast
::ExprKind
::Continue(opt_ident
) => {
2219 self.s
.word("continue")?
;
2221 if let Some(ident
) = opt_ident
{
2222 self.print_ident(ident
.node
)?
;
2226 ast
::ExprKind
::Ret(ref result
) => {
2227 self.s
.word("return")?
;
2228 if let Some(ref expr
) = *result
{
2230 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
)?
;
2233 ast
::ExprKind
::InlineAsm(ref a
) => {
2234 self.s
.word("asm!")?
;
2236 self.print_string(&a
.asm
.as_str(), a
.asm_str_style
)?
;
2237 self.word_space(":")?
;
2239 self.commasep(Inconsistent
, &a
.outputs
, |s
, out
| {
2240 let constraint
= out
.constraint
.as_str();
2241 let mut ch
= constraint
.chars();
2243 Some('
='
) if out
.is_rw
=> {
2244 s
.print_string(&format
!("+{}", ch
.as_str()),
2245 ast
::StrStyle
::Cooked
)?
2247 _
=> s
.print_string(&constraint
, ast
::StrStyle
::Cooked
)?
2250 s
.print_expr(&out
.expr
)?
;
2255 self.word_space(":")?
;
2257 self.commasep(Inconsistent
, &a
.inputs
, |s
, &(co
, ref o
)| {
2258 s
.print_string(&co
.as_str(), ast
::StrStyle
::Cooked
)?
;
2265 self.word_space(":")?
;
2267 self.commasep(Inconsistent
, &a
.clobbers
,
2269 s
.print_string(&co
.as_str(), ast
::StrStyle
::Cooked
)?
;
2273 let mut options
= vec
![];
2275 options
.push("volatile");
2278 options
.push("alignstack");
2280 if a
.dialect
== ast
::AsmDialect
::Intel
{
2281 options
.push("intel");
2284 if !options
.is_empty() {
2286 self.word_space(":")?
;
2287 self.commasep(Inconsistent
, &options
,
2289 s
.print_string(co
, ast
::StrStyle
::Cooked
)?
;
2296 ast
::ExprKind
::Mac(ref m
) => self.print_mac(m
, token
::Paren
)?
,
2297 ast
::ExprKind
::Paren(ref e
) => {
2299 self.print_inner_attributes_inline(attrs
)?
;
2300 self.print_expr(e
)?
;
2303 ast
::ExprKind
::Yield(ref e
) => {
2304 self.s
.word("yield")?
;
2308 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
)?
;
2313 ast
::ExprKind
::Try(ref e
) => {
2314 self.print_expr_maybe_paren(e
, parser
::PREC_POSTFIX
)?
;
2317 ast
::ExprKind
::Catch(ref blk
) => {
2318 self.head("do catch")?
;
2320 self.print_block_with_attrs(blk
, attrs
)?
2323 self.ann
.post(self, NodeExpr(expr
))?
;
2327 pub fn print_local_decl(&mut self, loc
: &ast
::Local
) -> io
::Result
<()> {
2328 self.print_pat(&loc
.pat
)?
;
2329 if let Some(ref ty
) = loc
.ty
{
2330 self.word_space(":")?
;
2331 self.print_type(ty
)?
;
2336 pub fn print_ident(&mut self, ident
: ast
::Ident
) -> io
::Result
<()> {
2337 self.s
.word(&ident
.name
.as_str())?
;
2338 self.ann
.post(self, NodeIdent(&ident
))
2341 pub fn print_usize(&mut self, i
: usize) -> io
::Result
<()> {
2342 self.s
.word(&i
.to_string())
2345 pub fn print_name(&mut self, name
: ast
::Name
) -> io
::Result
<()> {
2346 self.s
.word(&name
.as_str())?
;
2347 self.ann
.post(self, NodeName(&name
))
2350 pub fn print_for_decl(&mut self, loc
: &ast
::Local
,
2351 coll
: &ast
::Expr
) -> io
::Result
<()> {
2352 self.print_local_decl(loc
)?
;
2354 self.word_space("in")?
;
2355 self.print_expr(coll
)
2358 fn print_path(&mut self,
2360 colons_before_params
: bool
,
2362 defaults_to_global
: bool
)
2365 self.maybe_print_comment(path
.span
.lo())?
;
2367 let mut segments
= path
.segments
[..path
.segments
.len()-depth
].iter();
2368 if defaults_to_global
&& path
.is_global() {
2371 for (i
, segment
) in segments
.enumerate() {
2375 self.print_path_segment(segment
, colons_before_params
)?
;
2381 fn print_path_segment(&mut self,
2382 segment
: &ast
::PathSegment
,
2383 colons_before_params
: bool
)
2386 if segment
.identifier
.name
!= keywords
::CrateRoot
.name() &&
2387 segment
.identifier
.name
!= keywords
::DollarCrate
.name() {
2388 self.print_ident(segment
.identifier
)?
;
2389 if let Some(ref parameters
) = segment
.parameters
{
2390 self.print_path_parameters(parameters
, colons_before_params
)?
;
2396 fn print_qpath(&mut self,
2399 colons_before_params
: bool
)
2403 self.print_type(&qself
.ty
)?
;
2404 if qself
.position
> 0 {
2406 self.word_space("as")?
;
2407 let depth
= path
.segments
.len() - qself
.position
;
2408 self.print_path(path
, false, depth
, false)?
;
2412 let item_segment
= path
.segments
.last().unwrap();
2413 self.print_ident(item_segment
.identifier
)?
;
2414 match item_segment
.parameters
{
2415 Some(ref parameters
) => self.print_path_parameters(parameters
, colons_before_params
),
2420 fn print_path_parameters(&mut self,
2421 parameters
: &ast
::PathParameters
,
2422 colons_before_params
: bool
)
2425 if colons_before_params
{
2430 ast
::PathParameters
::AngleBracketed(ref data
) => {
2433 let mut comma
= false;
2434 for lifetime
in &data
.lifetimes
{
2436 self.word_space(",")?
2438 self.print_lifetime(lifetime
)?
;
2442 if !data
.types
.is_empty() {
2444 self.word_space(",")?
2449 |s
, ty
| s
.print_type(ty
))?
;
2453 for binding
in data
.bindings
.iter() {
2455 self.word_space(",")?
2457 self.print_ident(binding
.ident
)?
;
2459 self.word_space("=")?
;
2460 self.print_type(&binding
.ty
)?
;
2467 ast
::PathParameters
::Parenthesized(ref data
) => {
2472 |s
, ty
| s
.print_type(ty
))?
;
2475 if let Some(ref ty
) = data
.output
{
2476 self.space_if_not_bol()?
;
2477 self.word_space("->")?
;
2478 self.print_type(ty
)?
;
2486 pub fn print_pat(&mut self, pat
: &ast
::Pat
) -> io
::Result
<()> {
2487 self.maybe_print_comment(pat
.span
.lo())?
;
2488 self.ann
.pre(self, NodePat(pat
))?
;
2489 /* Pat isn't normalized, but the beauty of it
2490 is that it doesn't matter */
2492 PatKind
::Wild
=> self.s
.word("_")?
,
2493 PatKind
::Ident(binding_mode
, ref path1
, ref sub
) => {
2494 match binding_mode
{
2495 ast
::BindingMode
::ByRef(mutbl
) => {
2496 self.word_nbsp("ref")?
;
2497 self.print_mutability(mutbl
)?
;
2499 ast
::BindingMode
::ByValue(ast
::Mutability
::Immutable
) => {}
2500 ast
::BindingMode
::ByValue(ast
::Mutability
::Mutable
) => {
2501 self.word_nbsp("mut")?
;
2504 self.print_ident(path1
.node
)?
;
2505 if let Some(ref p
) = *sub
{
2510 PatKind
::TupleStruct(ref path
, ref elts
, ddpos
) => {
2511 self.print_path(path
, true, 0, false)?
;
2513 if let Some(ddpos
) = ddpos
{
2514 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(p
))?
;
2516 self.word_space(",")?
;
2519 if ddpos
!= elts
.len() {
2521 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(p
))?
;
2524 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
))?
;
2528 PatKind
::Path(None
, ref path
) => {
2529 self.print_path(path
, true, 0, false)?
;
2531 PatKind
::Path(Some(ref qself
), ref path
) => {
2532 self.print_qpath(path
, qself
, false)?
;
2534 PatKind
::Struct(ref path
, ref fields
, etc
) => {
2535 self.print_path(path
, true, 0, false)?
;
2537 self.word_space("{")?
;
2539 Consistent
, &fields
[..],
2541 s
.cbox(INDENT_UNIT
)?
;
2542 if !f
.node
.is_shorthand
{
2543 s
.print_ident(f
.node
.ident
)?
;
2546 s
.print_pat(&f
.node
.pat
)?
;
2549 |f
| f
.node
.pat
.span
)?
;
2551 if !fields
.is_empty() { self.word_space(",")?; }
2557 PatKind
::Tuple(ref elts
, ddpos
) => {
2559 if let Some(ddpos
) = ddpos
{
2560 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(p
))?
;
2562 self.word_space(",")?
;
2565 if ddpos
!= elts
.len() {
2567 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(p
))?
;
2570 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
))?
;
2571 if elts
.len() == 1 {
2577 PatKind
::Box(ref inner
) => {
2578 self.s
.word("box ")?
;
2579 self.print_pat(inner
)?
;
2581 PatKind
::Ref(ref inner
, mutbl
) => {
2583 if mutbl
== ast
::Mutability
::Mutable
{
2584 self.s
.word("mut ")?
;
2586 self.print_pat(inner
)?
;
2588 PatKind
::Lit(ref e
) => self.print_expr(&**e
)?
,
2589 PatKind
::Range(ref begin
, ref end
, ref end_kind
) => {
2590 self.print_expr(begin
)?
;
2593 RangeEnd
::Included(RangeSyntax
::DotDotDot
) => self.s
.word("...")?
,
2594 RangeEnd
::Included(RangeSyntax
::DotDotEq
) => self.s
.word("..=")?
,
2595 RangeEnd
::Excluded
=> self.s
.word("..")?
,
2597 self.print_expr(end
)?
;
2599 PatKind
::Slice(ref before
, ref slice
, ref after
) => {
2601 self.commasep(Inconsistent
,
2603 |s
, p
| s
.print_pat(p
))?
;
2604 if let Some(ref p
) = *slice
{
2605 if !before
.is_empty() { self.word_space(",")?; }
2606 if p
.node
!= PatKind
::Wild
{
2610 if !after
.is_empty() { self.word_space(",")?; }
2612 self.commasep(Inconsistent
,
2614 |s
, p
| s
.print_pat(p
))?
;
2617 PatKind
::Mac(ref m
) => self.print_mac(m
, token
::Paren
)?
,
2619 self.ann
.post(self, NodePat(pat
))
2622 fn print_arm(&mut self, arm
: &ast
::Arm
) -> io
::Result
<()> {
2623 // I have no idea why this check is necessary, but here it
2625 if arm
.attrs
.is_empty() {
2628 self.cbox(INDENT_UNIT
)?
;
2630 self.maybe_print_comment(arm
.pats
[0].span
.lo())?
;
2631 self.print_outer_attributes(&arm
.attrs
)?
;
2632 let mut first
= true;
2633 for p
in &arm
.pats
{
2638 self.word_space("|")?
;
2643 if let Some(ref e
) = arm
.guard
{
2644 self.word_space("if")?
;
2645 self.print_expr(e
)?
;
2648 self.word_space("=>")?
;
2650 match arm
.body
.node
{
2651 ast
::ExprKind
::Block(ref blk
) => {
2652 // the block will close the pattern's ibox
2653 self.print_block_unclosed_indent(blk
, INDENT_UNIT
)?
;
2655 // If it is a user-provided unsafe block, print a comma after it
2656 if let BlockCheckMode
::Unsafe(ast
::UserProvided
) = blk
.rules
{
2661 self.end()?
; // close the ibox for the pattern
2662 self.print_expr(&arm
.body
)?
;
2666 self.end() // close enclosing cbox
2669 fn print_explicit_self(&mut self, explicit_self
: &ast
::ExplicitSelf
) -> io
::Result
<()> {
2670 match explicit_self
.node
{
2671 SelfKind
::Value(m
) => {
2672 self.print_mutability(m
)?
;
2675 SelfKind
::Region(ref lt
, m
) => {
2677 self.print_opt_lifetime(lt
)?
;
2678 self.print_mutability(m
)?
;
2681 SelfKind
::Explicit(ref typ
, m
) => {
2682 self.print_mutability(m
)?
;
2683 self.s
.word("self")?
;
2684 self.word_space(":")?
;
2685 self.print_type(typ
)
2690 pub fn print_fn(&mut self,
2692 unsafety
: ast
::Unsafety
,
2693 constness
: ast
::Constness
,
2695 name
: Option
<ast
::Ident
>,
2696 generics
: &ast
::Generics
,
2697 vis
: &ast
::Visibility
) -> io
::Result
<()> {
2698 self.print_fn_header_info(unsafety
, constness
, abi
, vis
)?
;
2700 if let Some(name
) = name
{
2702 self.print_ident(name
)?
;
2704 self.print_generics(generics
)?
;
2705 self.print_fn_args_and_ret(decl
)?
;
2706 self.print_where_clause(&generics
.where_clause
)
2709 pub fn print_fn_args_and_ret(&mut self, decl
: &ast
::FnDecl
)
2712 self.commasep(Inconsistent
, &decl
.inputs
, |s
, arg
| s
.print_arg(arg
, false))?
;
2714 self.s
.word(", ...")?
;
2718 self.print_fn_output(decl
)
2721 pub fn print_fn_block_args(
2726 self.commasep(Inconsistent
, &decl
.inputs
, |s
, arg
| s
.print_arg(arg
, true))?
;
2729 if let ast
::FunctionRetTy
::Default(..) = decl
.output
{
2733 self.space_if_not_bol()?
;
2734 self.word_space("->")?
;
2736 ast
::FunctionRetTy
::Ty(ref ty
) => {
2737 self.print_type(ty
)?
;
2738 self.maybe_print_comment(ty
.span
.lo())
2740 ast
::FunctionRetTy
::Default(..) => unreachable
!(),
2744 pub fn print_capture_clause(&mut self, capture_clause
: ast
::CaptureBy
)
2746 match capture_clause
{
2747 ast
::CaptureBy
::Value
=> self.word_space("move"),
2748 ast
::CaptureBy
::Ref
=> Ok(()),
2752 pub fn print_bounds(&mut self,
2754 bounds
: &[ast
::TyParamBound
])
2756 if !bounds
.is_empty() {
2757 self.s
.word(prefix
)?
;
2758 let mut first
= true;
2759 for bound
in bounds
{
2764 self.word_space("+")?
;
2768 TraitTyParamBound(ref tref
, TraitBoundModifier
::None
) => {
2769 self.print_poly_trait_ref(tref
)
2771 TraitTyParamBound(ref tref
, TraitBoundModifier
::Maybe
) => {
2773 self.print_poly_trait_ref(tref
)
2775 RegionTyParamBound(ref lt
) => {
2776 self.print_lifetime(lt
)
2786 pub fn print_lifetime(&mut self,
2787 lifetime
: &ast
::Lifetime
)
2790 self.print_name(lifetime
.ident
.name
)
2793 pub fn print_lifetime_bounds(&mut self,
2794 lifetime
: &ast
::Lifetime
,
2795 bounds
: &[ast
::Lifetime
])
2798 self.print_lifetime(lifetime
)?
;
2799 if !bounds
.is_empty() {
2801 for (i
, bound
) in bounds
.iter().enumerate() {
2803 self.s
.word(" + ")?
;
2805 self.print_lifetime(bound
)?
;
2811 pub fn print_generics(&mut self,
2812 generics
: &ast
::Generics
)
2815 let total
= generics
.lifetimes
.len() + generics
.ty_params
.len();
2822 let mut ints
= Vec
::new();
2827 self.commasep(Inconsistent
, &ints
[..], |s
, &idx
| {
2828 if idx
< generics
.lifetimes
.len() {
2829 let lifetime_def
= &generics
.lifetimes
[idx
];
2830 s
.print_outer_attributes_inline(&lifetime_def
.attrs
)?
;
2831 s
.print_lifetime_bounds(&lifetime_def
.lifetime
, &lifetime_def
.bounds
)
2833 let idx
= idx
- generics
.lifetimes
.len();
2834 let param
= &generics
.ty_params
[idx
];
2835 s
.print_ty_param(param
)
2843 pub fn print_ty_param(&mut self, param
: &ast
::TyParam
) -> io
::Result
<()> {
2844 self.print_outer_attributes_inline(¶m
.attrs
)?
;
2845 self.print_ident(param
.ident
)?
;
2846 self.print_bounds(":", ¶m
.bounds
)?
;
2847 match param
.default {
2848 Some(ref default) => {
2850 self.word_space("=")?
;
2851 self.print_type(default)
2857 pub fn print_where_clause(&mut self, where_clause
: &ast
::WhereClause
)
2859 if where_clause
.predicates
.is_empty() {
2864 self.word_space("where")?
;
2866 for (i
, predicate
) in where_clause
.predicates
.iter().enumerate() {
2868 self.word_space(",")?
;
2872 ast
::WherePredicate
::BoundPredicate(ast
::WhereBoundPredicate
{ref bound_lifetimes
,
2876 self.print_formal_lifetime_list(bound_lifetimes
)?
;
2877 self.print_type(bounded_ty
)?
;
2878 self.print_bounds(":", bounds
)?
;
2880 ast
::WherePredicate
::RegionPredicate(ast
::WhereRegionPredicate
{ref lifetime
,
2883 self.print_lifetime_bounds(lifetime
, bounds
)?
;
2885 ast
::WherePredicate
::EqPredicate(ast
::WhereEqPredicate
{ref lhs_ty
,
2888 self.print_type(lhs_ty
)?
;
2890 self.word_space("=")?
;
2891 self.print_type(rhs_ty
)?
;
2899 pub fn print_view_path(&mut self, vp
: &ast
::ViewPath
) -> io
::Result
<()> {
2901 ast
::ViewPathSimple(ident
, ref path
) => {
2902 self.print_path(path
, false, 0, true)?
;
2904 if path
.segments
.last().unwrap().identifier
.name
!=
2907 self.word_space("as")?
;
2908 self.print_ident(ident
)?
;
2914 ast
::ViewPathGlob(ref path
) => {
2915 self.print_path(path
, false, 0, true)?
;
2919 ast
::ViewPathList(ref path
, ref idents
) => {
2920 if path
.segments
.is_empty() {
2923 self.print_path(path
, false, 0, true)?
;
2924 self.s
.word("::{")?
;
2926 self.commasep(Inconsistent
, &idents
[..], |s
, w
| {
2927 s
.print_ident(w
.node
.name
)?
;
2928 if let Some(ident
) = w
.node
.rename
{
2930 s
.word_space("as")?
;
2931 s
.print_ident(ident
)?
;
2940 pub fn print_mutability(&mut self,
2941 mutbl
: ast
::Mutability
) -> io
::Result
<()> {
2943 ast
::Mutability
::Mutable
=> self.word_nbsp("mut"),
2944 ast
::Mutability
::Immutable
=> Ok(()),
2948 pub fn print_mt(&mut self, mt
: &ast
::MutTy
) -> io
::Result
<()> {
2949 self.print_mutability(mt
.mutbl
)?
;
2950 self.print_type(&mt
.ty
)
2953 pub fn print_arg(&mut self, input
: &ast
::Arg
, is_closure
: bool
) -> io
::Result
<()> {
2954 self.ibox(INDENT_UNIT
)?
;
2955 match input
.ty
.node
{
2956 ast
::TyKind
::Infer
if is_closure
=> self.print_pat(&input
.pat
)?
,
2958 if let Some(eself
) = input
.to_self() {
2959 self.print_explicit_self(&eself
)?
;
2961 let invalid
= if let PatKind
::Ident(_
, ident
, _
) = input
.pat
.node
{
2962 ident
.node
.name
== keywords
::Invalid
.name()
2967 self.print_pat(&input
.pat
)?
;
2971 self.print_type(&input
.ty
)?
;
2978 pub fn print_fn_output(&mut self, decl
: &ast
::FnDecl
) -> io
::Result
<()> {
2979 if let ast
::FunctionRetTy
::Default(..) = decl
.output
{
2983 self.space_if_not_bol()?
;
2984 self.ibox(INDENT_UNIT
)?
;
2985 self.word_space("->")?
;
2987 ast
::FunctionRetTy
::Default(..) => unreachable
!(),
2988 ast
::FunctionRetTy
::Ty(ref ty
) =>
2989 self.print_type(ty
)?
2994 ast
::FunctionRetTy
::Ty(ref output
) => self.maybe_print_comment(output
.span
.lo()),
2999 pub fn print_ty_fn(&mut self,
3001 unsafety
: ast
::Unsafety
,
3003 name
: Option
<ast
::Ident
>,
3004 generics
: &ast
::Generics
)
3006 self.ibox(INDENT_UNIT
)?
;
3007 if !generics
.lifetimes
.is_empty() || !generics
.ty_params
.is_empty() {
3008 self.s
.word("for")?
;
3009 self.print_generics(generics
)?
;
3011 let generics
= ast
::Generics
{
3012 lifetimes
: Vec
::new(),
3013 ty_params
: Vec
::new(),
3014 where_clause
: ast
::WhereClause
{
3015 id
: ast
::DUMMY_NODE_ID
,
3016 predicates
: Vec
::new(),
3017 span
: syntax_pos
::DUMMY_SP
,
3019 span
: syntax_pos
::DUMMY_SP
,
3023 ast
::Constness
::NotConst
,
3027 &ast
::Visibility
::Inherited
)?
;
3031 pub fn maybe_print_trailing_comment(&mut self, span
: syntax_pos
::Span
,
3032 next_pos
: Option
<BytePos
>)
3034 let cm
= match self.cm
{
3038 if let Some(ref cmnt
) = self.next_comment() {
3039 if cmnt
.style
!= comments
::Trailing { return Ok(()) }
3040 let span_line
= cm
.lookup_char_pos(span
.hi());
3041 let comment_line
= cm
.lookup_char_pos(cmnt
.pos
);
3042 let next
= next_pos
.unwrap_or(cmnt
.pos
+ BytePos(1));
3043 if span
.hi() < cmnt
.pos
&& cmnt
.pos
< next
&& span_line
.line
== comment_line
.line
{
3044 self.print_comment(cmnt
)?
;
3050 pub fn print_remaining_comments(&mut self) -> io
::Result
<()> {
3051 // If there aren't any remaining comments, then we need to manually
3052 // make sure there is a line break at the end.
3053 if self.next_comment().is_none() {
3054 self.s
.hardbreak()?
;
3056 while let Some(ref cmnt
) = self.next_comment() {
3057 self.print_comment(cmnt
)?
;
3062 pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
3063 opt_abi
: Option
<Abi
>)
3066 Some(Abi
::Rust
) => Ok(()),
3068 self.word_nbsp("extern")?
;
3069 self.word_nbsp(&abi
.to_string())
3075 pub fn print_extern_opt_abi(&mut self,
3076 opt_abi
: Option
<Abi
>) -> io
::Result
<()> {
3079 self.word_nbsp("extern")?
;
3080 self.word_nbsp(&abi
.to_string())
3086 pub fn print_fn_header_info(&mut self,
3087 unsafety
: ast
::Unsafety
,
3088 constness
: ast
::Constness
,
3090 vis
: &ast
::Visibility
) -> io
::Result
<()> {
3091 self.s
.word(&visibility_qualified(vis
, ""))?
;
3094 ast
::Constness
::NotConst
=> {}
3095 ast
::Constness
::Const
=> self.word_nbsp("const")?
3098 self.print_unsafety(unsafety
)?
;
3100 if abi
!= Abi
::Rust
{
3101 self.word_nbsp("extern")?
;
3102 self.word_nbsp(&abi
.to_string())?
;
3108 pub fn print_unsafety(&mut self, s
: ast
::Unsafety
) -> io
::Result
<()> {
3110 ast
::Unsafety
::Normal
=> Ok(()),
3111 ast
::Unsafety
::Unsafe
=> self.word_nbsp("unsafe"),
3116 fn repeat(s
: &str, n
: usize) -> String { iter::repeat(s).take(n).collect() }
3127 fn test_fun_to_string() {
3128 let abba_ident
= ast
::Ident
::from_str("abba");
3130 let decl
= ast
::FnDecl
{
3132 output
: ast
::FunctionRetTy
::Default(syntax_pos
::DUMMY_SP
),
3135 let generics
= ast
::Generics
::default();
3136 assert_eq
!(fun_to_string(&decl
, ast
::Unsafety
::Normal
,
3137 ast
::Constness
::NotConst
,
3138 abba_ident
, &generics
),
3143 fn test_variant_to_string() {
3144 let ident
= ast
::Ident
::from_str("principal_skinner");
3146 let var
= codemap
::respan(syntax_pos
::DUMMY_SP
, ast
::Variant_
{
3149 // making this up as I go.... ?
3150 data
: ast
::VariantData
::Unit(ast
::DUMMY_NODE_ID
),
3154 let varstr
= variant_to_string(&var
);
3155 assert_eq
!(varstr
, "principal_skinner");