]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/print/pprust.rs
Rollup merge of #34403 - jonathandturner:move_liberror, r=alexcrichton
[rust.git] / src / libsyntax / print / pprust.rs
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.
4 //
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.
10
11 pub use self::AnnNode::*;
12
13 use abi::{self, Abi};
14 use ast::{self, TokenTree, BlockCheckMode, PatKind};
15 use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
16 use ast::Attribute;
17 use attr::ThinAttributesExt;
18 use util::parser::AssocOp;
19 use attr;
20 use attr::{AttrMetaMethods, AttributeMethods};
21 use codemap::{self, CodeMap};
22 use syntax_pos::{self, BytePos};
23 use errors;
24 use parse::token::{self, keywords, BinOpToken, Token, InternedString};
25 use parse::lexer::comments;
26 use parse;
27 use print::pp::{self, break_offset, word, space, zerobreak, hardbreak};
28 use print::pp::{Breaks, eof};
29 use print::pp::Breaks::{Consistent, Inconsistent};
30 use ptr::P;
31 use std_inject;
32
33 use std::ascii;
34 use std::io::{self, Write, Read};
35 use std::iter;
36
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),
45 }
46
47 pub trait PpAnn {
48     fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
49     fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
50 }
51
52 #[derive(Copy, Clone)]
53 pub struct NoAnn;
54
55 impl PpAnn for NoAnn {}
56
57 #[derive(Copy, Clone)]
58 pub struct CurrentCommentAndLiteral {
59     pub cur_cmnt: usize,
60     pub cur_lit: usize,
61 }
62
63 pub struct State<'a> {
64     pub s: pp::Printer<'a>,
65     cm: Option<&'a CodeMap>,
66     comments: Option<Vec<comments::Comment> >,
67     literals: Option<Vec<comments::Literal> >,
68     cur_cmnt_and_lit: CurrentCommentAndLiteral,
69     boxes: Vec<pp::Breaks>,
70     ann: &'a (PpAnn+'a),
71 }
72
73 pub fn rust_printer<'a>(writer: Box<Write+'a>) -> State<'a> {
74     static NO_ANN: NoAnn = NoAnn;
75     rust_printer_annotated(writer, &NO_ANN)
76 }
77
78 pub fn rust_printer_annotated<'a>(writer: Box<Write+'a>,
79                                   ann: &'a PpAnn) -> State<'a> {
80     State {
81         s: pp::mk_printer(writer, DEFAULT_COLUMNS),
82         cm: None,
83         comments: None,
84         literals: None,
85         cur_cmnt_and_lit: CurrentCommentAndLiteral {
86             cur_cmnt: 0,
87             cur_lit: 0
88         },
89         boxes: Vec::new(),
90         ann: ann,
91     }
92 }
93
94 pub const INDENT_UNIT: usize = 4;
95
96 pub const DEFAULT_COLUMNS: usize = 78;
97
98 /// Requires you to pass an input filename and reader so that
99 /// it can scan the input text for comments and literals to
100 /// copy forward.
101 pub fn print_crate<'a>(cm: &'a CodeMap,
102                        span_diagnostic: &errors::Handler,
103                        krate: &ast::Crate,
104                        filename: String,
105                        input: &mut Read,
106                        out: Box<Write+'a>,
107                        ann: &'a PpAnn,
108                        is_expanded: bool) -> io::Result<()> {
109     let mut s = State::new_from_input(cm,
110                                       span_diagnostic,
111                                       filename,
112                                       input,
113                                       out,
114                                       ann,
115                                       is_expanded);
116     if is_expanded && !std_inject::no_std(krate) {
117         // We need to print `#![no_std]` (and its feature gate) so that
118         // compiling pretty-printed source won't inject libstd again.
119         // However we don't want these attributes in the AST because
120         // of the feature gate, so we fake them up here.
121
122         // #![feature(prelude_import)]
123         let prelude_import_meta = attr::mk_word_item(InternedString::new("prelude_import"));
124         let list = attr::mk_list_item(InternedString::new("feature"),
125                                       vec![prelude_import_meta]);
126         let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), list);
127         try!(s.print_attribute(&fake_attr));
128
129         // #![no_std]
130         let no_std_meta = attr::mk_word_item(InternedString::new("no_std"));
131         let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta);
132         try!(s.print_attribute(&fake_attr));
133     }
134
135     try!(s.print_mod(&krate.module, &krate.attrs));
136     try!(s.print_remaining_comments());
137     eof(&mut s.s)
138 }
139
140 impl<'a> State<'a> {
141     pub fn new_from_input(cm: &'a CodeMap,
142                           span_diagnostic: &errors::Handler,
143                           filename: String,
144                           input: &mut Read,
145                           out: Box<Write+'a>,
146                           ann: &'a PpAnn,
147                           is_expanded: bool) -> State<'a> {
148         let (cmnts, lits) = comments::gather_comments_and_literals(
149             span_diagnostic,
150             filename,
151             input);
152
153         State::new(
154             cm,
155             out,
156             ann,
157             Some(cmnts),
158             // If the code is post expansion, don't use the table of
159             // literals, since it doesn't correspond with the literals
160             // in the AST anymore.
161             if is_expanded { None } else { Some(lits) })
162     }
163
164     pub fn new(cm: &'a CodeMap,
165                out: Box<Write+'a>,
166                ann: &'a PpAnn,
167                comments: Option<Vec<comments::Comment>>,
168                literals: Option<Vec<comments::Literal>>) -> State<'a> {
169         State {
170             s: pp::mk_printer(out, DEFAULT_COLUMNS),
171             cm: Some(cm),
172             comments: comments,
173             literals: literals,
174             cur_cmnt_and_lit: CurrentCommentAndLiteral {
175                 cur_cmnt: 0,
176                 cur_lit: 0
177             },
178             boxes: Vec::new(),
179             ann: ann,
180         }
181     }
182 }
183
184 pub fn to_string<F>(f: F) -> String where
185     F: FnOnce(&mut State) -> io::Result<()>,
186 {
187     let mut wr = Vec::new();
188     {
189         let mut printer = rust_printer(Box::new(&mut wr));
190         f(&mut printer).unwrap();
191         eof(&mut printer.s).unwrap();
192     }
193     String::from_utf8(wr).unwrap()
194 }
195
196 pub fn binop_to_string(op: BinOpToken) -> &'static str {
197     match op {
198         token::Plus     => "+",
199         token::Minus    => "-",
200         token::Star     => "*",
201         token::Slash    => "/",
202         token::Percent  => "%",
203         token::Caret    => "^",
204         token::And      => "&",
205         token::Or       => "|",
206         token::Shl      => "<<",
207         token::Shr      => ">>",
208     }
209 }
210
211 pub fn token_to_string(tok: &Token) -> String {
212     match *tok {
213         token::Eq                   => "=".to_string(),
214         token::Lt                   => "<".to_string(),
215         token::Le                   => "<=".to_string(),
216         token::EqEq                 => "==".to_string(),
217         token::Ne                   => "!=".to_string(),
218         token::Ge                   => ">=".to_string(),
219         token::Gt                   => ">".to_string(),
220         token::Not                  => "!".to_string(),
221         token::Tilde                => "~".to_string(),
222         token::OrOr                 => "||".to_string(),
223         token::AndAnd               => "&&".to_string(),
224         token::BinOp(op)            => binop_to_string(op).to_string(),
225         token::BinOpEq(op)          => format!("{}=", binop_to_string(op)),
226
227         /* Structural symbols */
228         token::At                   => "@".to_string(),
229         token::Dot                  => ".".to_string(),
230         token::DotDot               => "..".to_string(),
231         token::DotDotDot            => "...".to_string(),
232         token::Comma                => ",".to_string(),
233         token::Semi                 => ";".to_string(),
234         token::Colon                => ":".to_string(),
235         token::ModSep               => "::".to_string(),
236         token::RArrow               => "->".to_string(),
237         token::LArrow               => "<-".to_string(),
238         token::FatArrow             => "=>".to_string(),
239         token::OpenDelim(token::Paren) => "(".to_string(),
240         token::CloseDelim(token::Paren) => ")".to_string(),
241         token::OpenDelim(token::Bracket) => "[".to_string(),
242         token::CloseDelim(token::Bracket) => "]".to_string(),
243         token::OpenDelim(token::Brace) => "{".to_string(),
244         token::CloseDelim(token::Brace) => "}".to_string(),
245         token::Pound                => "#".to_string(),
246         token::Dollar               => "$".to_string(),
247         token::Question             => "?".to_string(),
248
249         /* Literals */
250         token::Literal(lit, suf) => {
251             let mut out = match lit {
252                 token::Byte(b)           => format!("b'{}'", b),
253                 token::Char(c)           => format!("'{}'", c),
254                 token::Float(c)          => c.to_string(),
255                 token::Integer(c)        => c.to_string(),
256                 token::Str_(s)           => format!("\"{}\"", s),
257                 token::StrRaw(s, n)      => format!("r{delim}\"{string}\"{delim}",
258                                                     delim=repeat("#", n),
259                                                     string=s),
260                 token::ByteStr(v)         => format!("b\"{}\"", v),
261                 token::ByteStrRaw(s, n)   => format!("br{delim}\"{string}\"{delim}",
262                                                     delim=repeat("#", n),
263                                                     string=s),
264             };
265
266             if let Some(s) = suf {
267                 out.push_str(&s.as_str())
268             }
269
270             out
271         }
272
273         /* Name components */
274         token::Ident(s)             => s.to_string(),
275         token::Lifetime(s)          => s.to_string(),
276         token::Underscore           => "_".to_string(),
277
278         /* Other */
279         token::DocComment(s)        => s.to_string(),
280         token::SubstNt(s)           => format!("${}", s),
281         token::MatchNt(s, t)        => format!("${}:{}", s, t),
282         token::Eof                  => "<eof>".to_string(),
283         token::Whitespace           => " ".to_string(),
284         token::Comment              => "/* */".to_string(),
285         token::Shebang(s)           => format!("/* shebang: {}*/", s),
286
287         token::SpecialVarNt(var)    => format!("${}", var.as_str()),
288
289         token::Interpolated(ref nt) => match *nt {
290             token::NtExpr(ref e)        => expr_to_string(&e),
291             token::NtMeta(ref e)        => meta_item_to_string(&e),
292             token::NtTy(ref e)          => ty_to_string(&e),
293             token::NtPath(ref e)        => path_to_string(&e),
294             token::NtItem(ref e)        => item_to_string(&e),
295             token::NtBlock(ref e)       => block_to_string(&e),
296             token::NtStmt(ref e)        => stmt_to_string(&e),
297             token::NtPat(ref e)         => pat_to_string(&e),
298             token::NtIdent(ref e)       => ident_to_string(e.node),
299             token::NtTT(ref e)          => tt_to_string(&e),
300             token::NtArm(ref e)         => arm_to_string(&e),
301             token::NtImplItem(ref e)    => impl_item_to_string(&e),
302             token::NtTraitItem(ref e)   => trait_item_to_string(&e),
303             token::NtGenerics(ref e)    => generics_to_string(&e),
304             token::NtWhereClause(ref e) => where_clause_to_string(&e),
305             token::NtArg(ref e)         => arg_to_string(&e),
306         }
307     }
308 }
309
310 pub fn ty_to_string(ty: &ast::Ty) -> String {
311     to_string(|s| s.print_type(ty))
312 }
313
314 pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String {
315     to_string(|s| s.print_bounds("", bounds))
316 }
317
318 pub fn pat_to_string(pat: &ast::Pat) -> String {
319     to_string(|s| s.print_pat(pat))
320 }
321
322 pub fn arm_to_string(arm: &ast::Arm) -> String {
323     to_string(|s| s.print_arm(arm))
324 }
325
326 pub fn expr_to_string(e: &ast::Expr) -> String {
327     to_string(|s| s.print_expr(e))
328 }
329
330 pub fn lifetime_to_string(e: &ast::Lifetime) -> String {
331     to_string(|s| s.print_lifetime(e))
332 }
333
334 pub fn tt_to_string(tt: &ast::TokenTree) -> String {
335     to_string(|s| s.print_tt(tt))
336 }
337
338 pub fn tts_to_string(tts: &[ast::TokenTree]) -> String {
339     to_string(|s| s.print_tts(tts))
340 }
341
342 pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
343     to_string(|s| s.print_stmt(stmt))
344 }
345
346 pub fn attr_to_string(attr: &ast::Attribute) -> String {
347     to_string(|s| s.print_attribute(attr))
348 }
349
350 pub fn item_to_string(i: &ast::Item) -> String {
351     to_string(|s| s.print_item(i))
352 }
353
354 pub fn impl_item_to_string(i: &ast::ImplItem) -> String {
355     to_string(|s| s.print_impl_item(i))
356 }
357
358 pub fn trait_item_to_string(i: &ast::TraitItem) -> String {
359     to_string(|s| s.print_trait_item(i))
360 }
361
362 pub fn generics_to_string(generics: &ast::Generics) -> String {
363     to_string(|s| s.print_generics(generics))
364 }
365
366 pub fn where_clause_to_string(i: &ast::WhereClause) -> String {
367     to_string(|s| s.print_where_clause(i))
368 }
369
370 pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
371     to_string(|s| s.print_fn_block_args(p))
372 }
373
374 pub fn path_to_string(p: &ast::Path) -> String {
375     to_string(|s| s.print_path(p, false, 0))
376 }
377
378 pub fn ident_to_string(id: ast::Ident) -> String {
379     to_string(|s| s.print_ident(id))
380 }
381
382 pub fn fun_to_string(decl: &ast::FnDecl,
383                      unsafety: ast::Unsafety,
384                      constness: ast::Constness,
385                      name: ast::Ident,
386                      generics: &ast::Generics)
387                      -> String {
388     to_string(|s| {
389         try!(s.head(""));
390         try!(s.print_fn(decl, unsafety, constness, Abi::Rust, Some(name),
391                    generics, &ast::Visibility::Inherited));
392         try!(s.end()); // Close the head box
393         s.end() // Close the outer box
394     })
395 }
396
397 pub fn block_to_string(blk: &ast::Block) -> String {
398     to_string(|s| {
399         // containing cbox, will be closed by print-block at }
400         try!(s.cbox(INDENT_UNIT));
401         // head-ibox, will be closed by print-block after {
402         try!(s.ibox(0));
403         s.print_block(blk)
404     })
405 }
406
407 pub fn meta_item_to_string(mi: &ast::MetaItem) -> String {
408     to_string(|s| s.print_meta_item(mi))
409 }
410
411 pub fn attribute_to_string(attr: &ast::Attribute) -> String {
412     to_string(|s| s.print_attribute(attr))
413 }
414
415 pub fn lit_to_string(l: &ast::Lit) -> String {
416     to_string(|s| s.print_literal(l))
417 }
418
419 pub fn variant_to_string(var: &ast::Variant) -> String {
420     to_string(|s| s.print_variant(var))
421 }
422
423 pub fn arg_to_string(arg: &ast::Arg) -> String {
424     to_string(|s| s.print_arg(arg, false))
425 }
426
427 pub fn mac_to_string(arg: &ast::Mac) -> String {
428     to_string(|s| s.print_mac(arg, ::parse::token::Paren))
429 }
430
431 pub fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
432     match *vis {
433         ast::Visibility::Public => format!("pub {}", s),
434         ast::Visibility::Crate(_) => format!("pub(crate) {}", s),
435         ast::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
436         ast::Visibility::Inherited => s.to_string()
437     }
438 }
439
440 fn needs_parentheses(expr: &ast::Expr) -> bool {
441     match expr.node {
442         ast::ExprKind::Assign(..) | ast::ExprKind::Binary(..) |
443         ast::ExprKind::Closure(..) |
444         ast::ExprKind::AssignOp(..) | ast::ExprKind::Cast(..) |
445         ast::ExprKind::InPlace(..) | ast::ExprKind::Type(..) => true,
446         _ => false,
447     }
448 }
449
450 pub trait PrintState<'a> {
451     fn writer(&mut self) -> &mut pp::Printer<'a>;
452     fn boxes(&mut self) -> &mut Vec<pp::Breaks>;
453     fn comments(&mut self) -> &mut Option<Vec<comments::Comment>>;
454     fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral;
455     fn literals(&self) -> &Option<Vec<comments::Literal>>;
456
457     fn word_space(&mut self, w: &str) -> io::Result<()> {
458         try!(word(self.writer(), w));
459         space(self.writer())
460     }
461
462     fn popen(&mut self) -> io::Result<()> { word(self.writer(), "(") }
463
464     fn pclose(&mut self) -> io::Result<()> { word(self.writer(), ")") }
465
466     fn is_begin(&mut self) -> bool {
467         match self.writer().last_token() {
468             pp::Token::Begin(_) => true,
469             _ => false,
470         }
471     }
472
473     fn is_end(&mut self) -> bool {
474         match self.writer().last_token() {
475             pp::Token::End => true,
476             _ => false,
477         }
478     }
479
480     // is this the beginning of a line?
481     fn is_bol(&mut self) -> bool {
482         self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok()
483     }
484
485     fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
486         if !self.is_bol() {
487             try!(hardbreak(self.writer()))
488         }
489         Ok(())
490     }
491
492     // "raw box"
493     fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
494         self.boxes().push(b);
495         pp::rbox(self.writer(), u, b)
496     }
497
498     fn ibox(&mut self, u: usize) -> io::Result<()> {
499         self.boxes().push(pp::Breaks::Inconsistent);
500         pp::ibox(self.writer(), u)
501     }
502
503     fn end(&mut self) -> io::Result<()> {
504         self.boxes().pop().unwrap();
505         pp::end(self.writer())
506     }
507
508     fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()>
509         where F: FnMut(&mut Self, &T) -> io::Result<()>,
510     {
511         try!(self.rbox(0, b));
512         let mut first = true;
513         for elt in elts {
514             if first { first = false; } else { try!(self.word_space(",")); }
515             try!(op(self, elt));
516         }
517         self.end()
518     }
519
520     fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
521         let mut cur_lit = self.cur_cmnt_and_lit().cur_lit;
522
523         let mut result = None;
524
525         if let &Some(ref lits) = self.literals()
526         {
527             while cur_lit < lits.len() {
528                 let ltrl = (*lits)[cur_lit].clone();
529                 if ltrl.pos > pos { break; }
530                 cur_lit += 1;
531                 if ltrl.pos == pos {
532                     result = Some(ltrl);
533                     break;
534                 }
535             }
536         }
537
538         self.cur_cmnt_and_lit().cur_lit = cur_lit;
539         result
540     }
541
542     fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
543         loop {
544             match self.next_comment() {
545                 Some(ref cmnt) => {
546                     if (*cmnt).pos < pos {
547                         try!(self.print_comment(cmnt));
548                         self.cur_cmnt_and_lit().cur_cmnt += 1;
549                     } else { break; }
550                 }
551                 _ => break
552             }
553         }
554         Ok(())
555     }
556
557     fn print_comment(&mut self,
558                      cmnt: &comments::Comment) -> io::Result<()> {
559         match cmnt.style {
560             comments::Mixed => {
561                 assert_eq!(cmnt.lines.len(), 1);
562                 try!(zerobreak(self.writer()));
563                 try!(word(self.writer(), &cmnt.lines[0]));
564                 zerobreak(self.writer())
565             }
566             comments::Isolated => {
567                 try!(self.hardbreak_if_not_bol());
568                 for line in &cmnt.lines {
569                     // Don't print empty lines because they will end up as trailing
570                     // whitespace
571                     if !line.is_empty() {
572                         try!(word(self.writer(), &line[..]));
573                     }
574                     try!(hardbreak(self.writer()));
575                 }
576                 Ok(())
577             }
578             comments::Trailing => {
579                 try!(word(self.writer(), " "));
580                 if cmnt.lines.len() == 1 {
581                     try!(word(self.writer(), &cmnt.lines[0]));
582                     hardbreak(self.writer())
583                 } else {
584                     try!(self.ibox(0));
585                     for line in &cmnt.lines {
586                         if !line.is_empty() {
587                             try!(word(self.writer(), &line[..]));
588                         }
589                         try!(hardbreak(self.writer()));
590                     }
591                     self.end()
592                 }
593             }
594             comments::BlankLine => {
595                 // We need to do at least one, possibly two hardbreaks.
596                 let is_semi = match self.writer().last_token() {
597                     pp::Token::String(s, _) => ";" == s,
598                     _ => false
599                 };
600                 if is_semi || self.is_begin() || self.is_end() {
601                     try!(hardbreak(self.writer()));
602                 }
603                 hardbreak(self.writer())
604             }
605         }
606     }
607
608     fn next_comment(&mut self) -> Option<comments::Comment> {
609         let cur_cmnt = self.cur_cmnt_and_lit().cur_cmnt;
610         match *self.comments() {
611             Some(ref cmnts) => {
612                 if cur_cmnt < cmnts.len() {
613                     Some(cmnts[cur_cmnt].clone())
614                 } else {
615                     None
616                 }
617             }
618             _ => None
619         }
620     }
621
622     fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
623         try!(self.maybe_print_comment(lit.span.lo));
624         match self.next_lit(lit.span.lo) {
625             Some(ref ltrl) => {
626                 return word(self.writer(), &(*ltrl).lit);
627             }
628             _ => ()
629         }
630         match lit.node {
631             ast::LitKind::Str(ref st, style) => self.print_string(&st, style),
632             ast::LitKind::Byte(byte) => {
633                 let mut res = String::from("b'");
634                 res.extend(ascii::escape_default(byte).map(|c| c as char));
635                 res.push('\'');
636                 word(self.writer(), &res[..])
637             }
638             ast::LitKind::Char(ch) => {
639                 let mut res = String::from("'");
640                 res.extend(ch.escape_default());
641                 res.push('\'');
642                 word(self.writer(), &res[..])
643             }
644             ast::LitKind::Int(i, t) => {
645                 match t {
646                     ast::LitIntType::Signed(st) => {
647                         word(self.writer(),
648                              &st.val_to_string(i as i64))
649                     }
650                     ast::LitIntType::Unsigned(ut) => {
651                         word(self.writer(), &ut.val_to_string(i))
652                     }
653                     ast::LitIntType::Unsuffixed => {
654                         word(self.writer(), &format!("{}", i))
655                     }
656                 }
657             }
658             ast::LitKind::Float(ref f, t) => {
659                 word(self.writer(),
660                      &format!(
661                          "{}{}",
662                          &f,
663                          t.ty_to_string()))
664             }
665             ast::LitKind::FloatUnsuffixed(ref f) => word(self.writer(), &f[..]),
666             ast::LitKind::Bool(val) => {
667                 if val { word(self.writer(), "true") } else { word(self.writer(), "false") }
668             }
669             ast::LitKind::ByteStr(ref v) => {
670                 let mut escaped: String = String::new();
671                 for &ch in v.iter() {
672                     escaped.extend(ascii::escape_default(ch)
673                                          .map(|c| c as char));
674                 }
675                 word(self.writer(), &format!("b\"{}\"", escaped))
676             }
677         }
678     }
679
680     fn print_string(&mut self, st: &str,
681                     style: ast::StrStyle) -> io::Result<()> {
682         let st = match style {
683             ast::StrStyle::Cooked => {
684                 (format!("\"{}\"", st.escape_default()))
685             }
686             ast::StrStyle::Raw(n) => {
687                 (format!("r{delim}\"{string}\"{delim}",
688                          delim=repeat("#", n),
689                          string=st))
690             }
691         };
692         word(self.writer(), &st[..])
693     }
694
695     fn print_inner_attributes(&mut self,
696                               attrs: &[ast::Attribute]) -> io::Result<()> {
697         self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true)
698     }
699
700     fn print_inner_attributes_no_trailing_hardbreak(&mut self,
701                                                    attrs: &[ast::Attribute])
702                                                    -> io::Result<()> {
703         self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false)
704     }
705
706     fn print_outer_attributes(&mut self,
707                               attrs: &[ast::Attribute]) -> io::Result<()> {
708         self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true)
709     }
710
711     fn print_inner_attributes_inline(&mut self,
712                                      attrs: &[ast::Attribute]) -> io::Result<()> {
713         self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true)
714     }
715
716     fn print_outer_attributes_inline(&mut self,
717                                      attrs: &[ast::Attribute]) -> io::Result<()> {
718         self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true)
719     }
720
721     fn print_either_attributes(&mut self,
722                               attrs: &[ast::Attribute],
723                               kind: ast::AttrStyle,
724                               is_inline: bool,
725                               trailing_hardbreak: bool) -> io::Result<()> {
726         let mut count = 0;
727         for attr in attrs {
728             if attr.node.style == kind {
729                 try!(self.print_attribute_inline(attr, is_inline));
730                 if is_inline {
731                     try!(self.nbsp());
732                 }
733                 count += 1;
734             }
735         }
736         if count > 0 && trailing_hardbreak && !is_inline {
737             try!(self.hardbreak_if_not_bol());
738         }
739         Ok(())
740     }
741
742     fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
743         self.print_attribute_inline(attr, false)
744     }
745
746     fn print_attribute_inline(&mut self, attr: &ast::Attribute,
747                               is_inline: bool) -> io::Result<()> {
748         if !is_inline {
749             try!(self.hardbreak_if_not_bol());
750         }
751         try!(self.maybe_print_comment(attr.span.lo));
752         if attr.node.is_sugared_doc {
753             try!(word(self.writer(), &attr.value_str().unwrap()));
754             hardbreak(self.writer())
755         } else {
756             match attr.node.style {
757                 ast::AttrStyle::Inner => try!(word(self.writer(), "#![")),
758                 ast::AttrStyle::Outer => try!(word(self.writer(), "#[")),
759             }
760             try!(self.print_meta_item(&attr.meta()));
761             word(self.writer(), "]")
762         }
763     }
764
765     fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
766         try!(self.ibox(INDENT_UNIT));
767         match item.node {
768             ast::MetaItemKind::Word(ref name) => {
769                 try!(word(self.writer(), &name));
770             }
771             ast::MetaItemKind::NameValue(ref name, ref value) => {
772                 try!(self.word_space(&name[..]));
773                 try!(self.word_space("="));
774                 try!(self.print_literal(value));
775             }
776             ast::MetaItemKind::List(ref name, ref items) => {
777                 try!(word(self.writer(), &name));
778                 try!(self.popen());
779                 try!(self.commasep(Consistent,
780                               &items[..],
781                               |s, i| s.print_meta_item(&i)));
782                 try!(self.pclose());
783             }
784         }
785         self.end()
786     }
787
788     fn space_if_not_bol(&mut self) -> io::Result<()> {
789         if !self.is_bol() { try!(space(self.writer())); }
790         Ok(())
791     }
792
793     fn nbsp(&mut self) -> io::Result<()> { word(self.writer(), " ") }
794 }
795
796 impl<'a> PrintState<'a> for State<'a> {
797     fn writer(&mut self) -> &mut pp::Printer<'a> {
798         &mut self.s
799     }
800
801     fn boxes(&mut self) -> &mut Vec<pp::Breaks> {
802         &mut self.boxes
803     }
804
805     fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> {
806         &mut self.comments
807     }
808
809     fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral {
810         &mut self.cur_cmnt_and_lit
811     }
812
813     fn literals(&self) -> &Option<Vec<comments::Literal>> {
814         &self.literals
815     }
816 }
817
818 impl<'a> State<'a> {
819     pub fn cbox(&mut self, u: usize) -> io::Result<()> {
820         self.boxes.push(pp::Breaks::Consistent);
821         pp::cbox(&mut self.s, u)
822     }
823
824     pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
825         try!(word(&mut self.s, w));
826         self.nbsp()
827     }
828
829     pub fn head(&mut self, w: &str) -> io::Result<()> {
830         // outer-box is consistent
831         try!(self.cbox(INDENT_UNIT));
832         // head-box is inconsistent
833         try!(self.ibox(w.len() + 1));
834         // keyword that starts the head
835         if !w.is_empty() {
836             try!(self.word_nbsp(w));
837         }
838         Ok(())
839     }
840
841     pub fn bopen(&mut self) -> io::Result<()> {
842         try!(word(&mut self.s, "{"));
843         self.end() // close the head-box
844     }
845
846     pub fn bclose_(&mut self, span: syntax_pos::Span,
847                    indented: usize) -> io::Result<()> {
848         self.bclose_maybe_open(span, indented, true)
849     }
850     pub fn bclose_maybe_open(&mut self, span: syntax_pos::Span,
851                              indented: usize, close_box: bool) -> io::Result<()> {
852         try!(self.maybe_print_comment(span.hi));
853         try!(self.break_offset_if_not_bol(1, -(indented as isize)));
854         try!(word(&mut self.s, "}"));
855         if close_box {
856             try!(self.end()); // close the outer-box
857         }
858         Ok(())
859     }
860     pub fn bclose(&mut self, span: syntax_pos::Span) -> io::Result<()> {
861         self.bclose_(span, INDENT_UNIT)
862     }
863
864     pub fn in_cbox(&self) -> bool {
865         match self.boxes.last() {
866             Some(&last_box) => last_box == pp::Breaks::Consistent,
867             None => false
868         }
869     }
870
871     pub fn break_offset_if_not_bol(&mut self, n: usize,
872                                    off: isize) -> io::Result<()> {
873         if !self.is_bol() {
874             break_offset(&mut self.s, n, off)
875         } else {
876             if off != 0 && self.s.last_token().is_hardbreak_tok() {
877                 // We do something pretty sketchy here: tuck the nonzero
878                 // offset-adjustment we were going to deposit along with the
879                 // break into the previous hardbreak.
880                 self.s.replace_last_token(pp::hardbreak_tok_offset(off));
881             }
882             Ok(())
883         }
884     }
885
886     // Synthesizes a comment that was not textually present in the original source
887     // file.
888     pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
889         try!(word(&mut self.s, "/*"));
890         try!(space(&mut self.s));
891         try!(word(&mut self.s, &text[..]));
892         try!(space(&mut self.s));
893         word(&mut self.s, "*/")
894     }
895
896
897
898     pub fn commasep_cmnt<T, F, G>(&mut self,
899                                   b: Breaks,
900                                   elts: &[T],
901                                   mut op: F,
902                                   mut get_span: G) -> io::Result<()> where
903         F: FnMut(&mut State, &T) -> io::Result<()>,
904         G: FnMut(&T) -> syntax_pos::Span,
905     {
906         try!(self.rbox(0, b));
907         let len = elts.len();
908         let mut i = 0;
909         for elt in elts {
910             try!(self.maybe_print_comment(get_span(elt).hi));
911             try!(op(self, elt));
912             i += 1;
913             if i < len {
914                 try!(word(&mut self.s, ","));
915                 try!(self.maybe_print_trailing_comment(get_span(elt),
916                                                   Some(get_span(&elts[i]).hi)));
917                 try!(self.space_if_not_bol());
918             }
919         }
920         self.end()
921     }
922
923     pub fn commasep_exprs(&mut self, b: Breaks,
924                           exprs: &[P<ast::Expr>]) -> io::Result<()> {
925         self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
926     }
927
928     pub fn print_mod(&mut self, _mod: &ast::Mod,
929                      attrs: &[ast::Attribute]) -> io::Result<()> {
930         try!(self.print_inner_attributes(attrs));
931         for item in &_mod.items {
932             try!(self.print_item(&item));
933         }
934         Ok(())
935     }
936
937     pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
938                              attrs: &[ast::Attribute]) -> io::Result<()> {
939         try!(self.print_inner_attributes(attrs));
940         for item in &nmod.items {
941             try!(self.print_foreign_item(item));
942         }
943         Ok(())
944     }
945
946     pub fn print_opt_lifetime(&mut self,
947                               lifetime: &Option<ast::Lifetime>) -> io::Result<()> {
948         if let Some(l) = *lifetime {
949             try!(self.print_lifetime(&l));
950             try!(self.nbsp());
951         }
952         Ok(())
953     }
954
955     pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
956         try!(self.maybe_print_comment(ty.span.lo));
957         try!(self.ibox(0));
958         match ty.node {
959             ast::TyKind::Vec(ref ty) => {
960                 try!(word(&mut self.s, "["));
961                 try!(self.print_type(&ty));
962                 try!(word(&mut self.s, "]"));
963             }
964             ast::TyKind::Ptr(ref mt) => {
965                 try!(word(&mut self.s, "*"));
966                 match mt.mutbl {
967                     ast::Mutability::Mutable => try!(self.word_nbsp("mut")),
968                     ast::Mutability::Immutable => try!(self.word_nbsp("const")),
969                 }
970                 try!(self.print_type(&mt.ty));
971             }
972             ast::TyKind::Rptr(ref lifetime, ref mt) => {
973                 try!(word(&mut self.s, "&"));
974                 try!(self.print_opt_lifetime(lifetime));
975                 try!(self.print_mt(mt));
976             }
977             ast::TyKind::Tup(ref elts) => {
978                 try!(self.popen());
979                 try!(self.commasep(Inconsistent, &elts[..],
980                               |s, ty| s.print_type(&ty)));
981                 if elts.len() == 1 {
982                     try!(word(&mut self.s, ","));
983                 }
984                 try!(self.pclose());
985             }
986             ast::TyKind::Paren(ref typ) => {
987                 try!(self.popen());
988                 try!(self.print_type(&typ));
989                 try!(self.pclose());
990             }
991             ast::TyKind::BareFn(ref f) => {
992                 let generics = ast::Generics {
993                     lifetimes: f.lifetimes.clone(),
994                     ty_params: P::new(),
995                     where_clause: ast::WhereClause {
996                         id: ast::DUMMY_NODE_ID,
997                         predicates: Vec::new(),
998                     },
999                 };
1000                 try!(self.print_ty_fn(f.abi,
1001                                  f.unsafety,
1002                                  &f.decl,
1003                                  None,
1004                                  &generics));
1005             }
1006             ast::TyKind::Path(None, ref path) => {
1007                 try!(self.print_path(path, false, 0));
1008             }
1009             ast::TyKind::Path(Some(ref qself), ref path) => {
1010                 try!(self.print_qpath(path, qself, false))
1011             }
1012             ast::TyKind::ObjectSum(ref ty, ref bounds) => {
1013                 try!(self.print_type(&ty));
1014                 try!(self.print_bounds("+", &bounds[..]));
1015             }
1016             ast::TyKind::PolyTraitRef(ref bounds) => {
1017                 try!(self.print_bounds("", &bounds[..]));
1018             }
1019             ast::TyKind::FixedLengthVec(ref ty, ref v) => {
1020                 try!(word(&mut self.s, "["));
1021                 try!(self.print_type(&ty));
1022                 try!(word(&mut self.s, "; "));
1023                 try!(self.print_expr(&v));
1024                 try!(word(&mut self.s, "]"));
1025             }
1026             ast::TyKind::Typeof(ref e) => {
1027                 try!(word(&mut self.s, "typeof("));
1028                 try!(self.print_expr(&e));
1029                 try!(word(&mut self.s, ")"));
1030             }
1031             ast::TyKind::Infer => {
1032                 try!(word(&mut self.s, "_"));
1033             }
1034             ast::TyKind::ImplicitSelf => {
1035                 try!(word(&mut self.s, "Self"));
1036             }
1037             ast::TyKind::Mac(ref m) => {
1038                 try!(self.print_mac(m, token::Paren));
1039             }
1040         }
1041         self.end()
1042     }
1043
1044     pub fn print_foreign_item(&mut self,
1045                               item: &ast::ForeignItem) -> io::Result<()> {
1046         try!(self.hardbreak_if_not_bol());
1047         try!(self.maybe_print_comment(item.span.lo));
1048         try!(self.print_outer_attributes(&item.attrs));
1049         match item.node {
1050             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
1051                 try!(self.head(""));
1052                 try!(self.print_fn(decl, ast::Unsafety::Normal,
1053                               ast::Constness::NotConst,
1054                               Abi::Rust, Some(item.ident),
1055                               generics, &item.vis));
1056                 try!(self.end()); // end head-ibox
1057                 try!(word(&mut self.s, ";"));
1058                 self.end() // end the outer fn box
1059             }
1060             ast::ForeignItemKind::Static(ref t, m) => {
1061                 try!(self.head(&visibility_qualified(&item.vis, "static")));
1062                 if m {
1063                     try!(self.word_space("mut"));
1064                 }
1065                 try!(self.print_ident(item.ident));
1066                 try!(self.word_space(":"));
1067                 try!(self.print_type(&t));
1068                 try!(word(&mut self.s, ";"));
1069                 try!(self.end()); // end the head-ibox
1070                 self.end() // end the outer cbox
1071             }
1072         }
1073     }
1074
1075     fn print_associated_const(&mut self,
1076                               ident: ast::Ident,
1077                               ty: &ast::Ty,
1078                               default: Option<&ast::Expr>,
1079                               vis: &ast::Visibility)
1080                               -> io::Result<()>
1081     {
1082         try!(word(&mut self.s, &visibility_qualified(vis, "")));
1083         try!(self.word_space("const"));
1084         try!(self.print_ident(ident));
1085         try!(self.word_space(":"));
1086         try!(self.print_type(ty));
1087         if let Some(expr) = default {
1088             try!(space(&mut self.s));
1089             try!(self.word_space("="));
1090             try!(self.print_expr(expr));
1091         }
1092         word(&mut self.s, ";")
1093     }
1094
1095     fn print_associated_type(&mut self,
1096                              ident: ast::Ident,
1097                              bounds: Option<&ast::TyParamBounds>,
1098                              ty: Option<&ast::Ty>)
1099                              -> io::Result<()> {
1100         try!(self.word_space("type"));
1101         try!(self.print_ident(ident));
1102         if let Some(bounds) = bounds {
1103             try!(self.print_bounds(":", bounds));
1104         }
1105         if let Some(ty) = ty {
1106             try!(space(&mut self.s));
1107             try!(self.word_space("="));
1108             try!(self.print_type(ty));
1109         }
1110         word(&mut self.s, ";")
1111     }
1112
1113     /// Pretty-print an item
1114     pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
1115         try!(self.hardbreak_if_not_bol());
1116         try!(self.maybe_print_comment(item.span.lo));
1117         try!(self.print_outer_attributes(&item.attrs));
1118         try!(self.ann.pre(self, NodeItem(item)));
1119         match item.node {
1120             ast::ItemKind::ExternCrate(ref optional_path) => {
1121                 try!(self.head(&visibility_qualified(&item.vis, "extern crate")));
1122                 if let Some(p) = *optional_path {
1123                     let val = p.as_str();
1124                     if val.contains("-") {
1125                         try!(self.print_string(&val, ast::StrStyle::Cooked));
1126                     } else {
1127                         try!(self.print_name(p));
1128                     }
1129                     try!(space(&mut self.s));
1130                     try!(word(&mut self.s, "as"));
1131                     try!(space(&mut self.s));
1132                 }
1133                 try!(self.print_ident(item.ident));
1134                 try!(word(&mut self.s, ";"));
1135                 try!(self.end()); // end inner head-block
1136                 try!(self.end()); // end outer head-block
1137             }
1138             ast::ItemKind::Use(ref vp) => {
1139                 try!(self.head(&visibility_qualified(&item.vis, "use")));
1140                 try!(self.print_view_path(&vp));
1141                 try!(word(&mut self.s, ";"));
1142                 try!(self.end()); // end inner head-block
1143                 try!(self.end()); // end outer head-block
1144             }
1145             ast::ItemKind::Static(ref ty, m, ref expr) => {
1146                 try!(self.head(&visibility_qualified(&item.vis, "static")));
1147                 if m == ast::Mutability::Mutable {
1148                     try!(self.word_space("mut"));
1149                 }
1150                 try!(self.print_ident(item.ident));
1151                 try!(self.word_space(":"));
1152                 try!(self.print_type(&ty));
1153                 try!(space(&mut self.s));
1154                 try!(self.end()); // end the head-ibox
1155
1156                 try!(self.word_space("="));
1157                 try!(self.print_expr(&expr));
1158                 try!(word(&mut self.s, ";"));
1159                 try!(self.end()); // end the outer cbox
1160             }
1161             ast::ItemKind::Const(ref ty, ref expr) => {
1162                 try!(self.head(&visibility_qualified(&item.vis, "const")));
1163                 try!(self.print_ident(item.ident));
1164                 try!(self.word_space(":"));
1165                 try!(self.print_type(&ty));
1166                 try!(space(&mut self.s));
1167                 try!(self.end()); // end the head-ibox
1168
1169                 try!(self.word_space("="));
1170                 try!(self.print_expr(&expr));
1171                 try!(word(&mut self.s, ";"));
1172                 try!(self.end()); // end the outer cbox
1173             }
1174             ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
1175                 try!(self.head(""));
1176                 try!(self.print_fn(
1177                     decl,
1178                     unsafety,
1179                     constness,
1180                     abi,
1181                     Some(item.ident),
1182                     typarams,
1183                     &item.vis
1184                 ));
1185                 try!(word(&mut self.s, " "));
1186                 try!(self.print_block_with_attrs(&body, &item.attrs));
1187             }
1188             ast::ItemKind::Mod(ref _mod) => {
1189                 try!(self.head(&visibility_qualified(&item.vis, "mod")));
1190                 try!(self.print_ident(item.ident));
1191                 try!(self.nbsp());
1192                 try!(self.bopen());
1193                 try!(self.print_mod(_mod, &item.attrs));
1194                 try!(self.bclose(item.span));
1195             }
1196             ast::ItemKind::ForeignMod(ref nmod) => {
1197                 try!(self.head("extern"));
1198                 try!(self.word_nbsp(&nmod.abi.to_string()));
1199                 try!(self.bopen());
1200                 try!(self.print_foreign_mod(nmod, &item.attrs));
1201                 try!(self.bclose(item.span));
1202             }
1203             ast::ItemKind::Ty(ref ty, ref params) => {
1204                 try!(self.ibox(INDENT_UNIT));
1205                 try!(self.ibox(0));
1206                 try!(self.word_nbsp(&visibility_qualified(&item.vis, "type")));
1207                 try!(self.print_ident(item.ident));
1208                 try!(self.print_generics(params));
1209                 try!(self.end()); // end the inner ibox
1210
1211                 try!(self.print_where_clause(&params.where_clause));
1212                 try!(space(&mut self.s));
1213                 try!(self.word_space("="));
1214                 try!(self.print_type(&ty));
1215                 try!(word(&mut self.s, ";"));
1216                 try!(self.end()); // end the outer ibox
1217             }
1218             ast::ItemKind::Enum(ref enum_definition, ref params) => {
1219                 try!(self.print_enum_def(
1220                     enum_definition,
1221                     params,
1222                     item.ident,
1223                     item.span,
1224                     &item.vis
1225                 ));
1226             }
1227             ast::ItemKind::Struct(ref struct_def, ref generics) => {
1228                 try!(self.head(&visibility_qualified(&item.vis, "struct")));
1229                 try!(self.print_struct(&struct_def, generics, item.ident, item.span, true));
1230             }
1231
1232             ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
1233                 try!(self.head(""));
1234                 try!(self.print_visibility(&item.vis));
1235                 try!(self.print_unsafety(unsafety));
1236                 try!(self.word_nbsp("impl"));
1237                 try!(self.print_trait_ref(trait_ref));
1238                 try!(space(&mut self.s));
1239                 try!(self.word_space("for"));
1240                 try!(self.word_space(".."));
1241                 try!(self.bopen());
1242                 try!(self.bclose(item.span));
1243             }
1244             ast::ItemKind::Impl(unsafety,
1245                           polarity,
1246                           ref generics,
1247                           ref opt_trait,
1248                           ref ty,
1249                           ref impl_items) => {
1250                 try!(self.head(""));
1251                 try!(self.print_visibility(&item.vis));
1252                 try!(self.print_unsafety(unsafety));
1253                 try!(self.word_nbsp("impl"));
1254
1255                 if generics.is_parameterized() {
1256                     try!(self.print_generics(generics));
1257                     try!(space(&mut self.s));
1258                 }
1259
1260                 match polarity {
1261                     ast::ImplPolarity::Negative => {
1262                         try!(word(&mut self.s, "!"));
1263                     },
1264                     _ => {}
1265                 }
1266
1267                 match *opt_trait {
1268                     Some(ref t) => {
1269                         try!(self.print_trait_ref(t));
1270                         try!(space(&mut self.s));
1271                         try!(self.word_space("for"));
1272                     }
1273                     None => {}
1274                 }
1275
1276                 try!(self.print_type(&ty));
1277                 try!(self.print_where_clause(&generics.where_clause));
1278
1279                 try!(space(&mut self.s));
1280                 try!(self.bopen());
1281                 try!(self.print_inner_attributes(&item.attrs));
1282                 for impl_item in impl_items {
1283                     try!(self.print_impl_item(impl_item));
1284                 }
1285                 try!(self.bclose(item.span));
1286             }
1287             ast::ItemKind::Trait(unsafety, ref generics, ref bounds, ref trait_items) => {
1288                 try!(self.head(""));
1289                 try!(self.print_visibility(&item.vis));
1290                 try!(self.print_unsafety(unsafety));
1291                 try!(self.word_nbsp("trait"));
1292                 try!(self.print_ident(item.ident));
1293                 try!(self.print_generics(generics));
1294                 let mut real_bounds = Vec::with_capacity(bounds.len());
1295                 for b in bounds.iter() {
1296                     if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
1297                         try!(space(&mut self.s));
1298                         try!(self.word_space("for ?"));
1299                         try!(self.print_trait_ref(&ptr.trait_ref));
1300                     } else {
1301                         real_bounds.push(b.clone());
1302                     }
1303                 }
1304                 try!(self.print_bounds(":", &real_bounds[..]));
1305                 try!(self.print_where_clause(&generics.where_clause));
1306                 try!(word(&mut self.s, " "));
1307                 try!(self.bopen());
1308                 for trait_item in trait_items {
1309                     try!(self.print_trait_item(trait_item));
1310                 }
1311                 try!(self.bclose(item.span));
1312             }
1313             ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
1314                 try!(self.print_visibility(&item.vis));
1315                 try!(self.print_path(&node.path, false, 0));
1316                 try!(word(&mut self.s, "! "));
1317                 try!(self.print_ident(item.ident));
1318                 try!(self.cbox(INDENT_UNIT));
1319                 try!(self.popen());
1320                 try!(self.print_tts(&node.tts[..]));
1321                 try!(self.pclose());
1322                 try!(word(&mut self.s, ";"));
1323                 try!(self.end());
1324             }
1325         }
1326         self.ann.post(self, NodeItem(item))
1327     }
1328
1329     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
1330         self.print_path(&t.path, false, 0)
1331     }
1332
1333     fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> {
1334         if !lifetimes.is_empty() {
1335             try!(word(&mut self.s, "for<"));
1336             let mut comma = false;
1337             for lifetime_def in lifetimes {
1338                 if comma {
1339                     try!(self.word_space(","))
1340                 }
1341                 try!(self.print_lifetime_def(lifetime_def));
1342                 comma = true;
1343             }
1344             try!(word(&mut self.s, ">"));
1345         }
1346         Ok(())
1347     }
1348
1349     fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> io::Result<()> {
1350         try!(self.print_formal_lifetime_list(&t.bound_lifetimes));
1351         self.print_trait_ref(&t.trait_ref)
1352     }
1353
1354     pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef,
1355                           generics: &ast::Generics, ident: ast::Ident,
1356                           span: syntax_pos::Span,
1357                           visibility: &ast::Visibility) -> io::Result<()> {
1358         try!(self.head(&visibility_qualified(visibility, "enum")));
1359         try!(self.print_ident(ident));
1360         try!(self.print_generics(generics));
1361         try!(self.print_where_clause(&generics.where_clause));
1362         try!(space(&mut self.s));
1363         self.print_variants(&enum_definition.variants, span)
1364     }
1365
1366     pub fn print_variants(&mut self,
1367                           variants: &[ast::Variant],
1368                           span: syntax_pos::Span) -> io::Result<()> {
1369         try!(self.bopen());
1370         for v in variants {
1371             try!(self.space_if_not_bol());
1372             try!(self.maybe_print_comment(v.span.lo));
1373             try!(self.print_outer_attributes(&v.node.attrs));
1374             try!(self.ibox(INDENT_UNIT));
1375             try!(self.print_variant(v));
1376             try!(word(&mut self.s, ","));
1377             try!(self.end());
1378             try!(self.maybe_print_trailing_comment(v.span, None));
1379         }
1380         self.bclose(span)
1381     }
1382
1383     pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
1384         match *vis {
1385             ast::Visibility::Public => self.word_nbsp("pub"),
1386             ast::Visibility::Crate(_) => self.word_nbsp("pub(crate)"),
1387             ast::Visibility::Restricted { ref path, .. } =>
1388                 self.word_nbsp(&format!("pub({})", path)),
1389             ast::Visibility::Inherited => Ok(())
1390         }
1391     }
1392
1393     pub fn print_struct(&mut self,
1394                         struct_def: &ast::VariantData,
1395                         generics: &ast::Generics,
1396                         ident: ast::Ident,
1397                         span: syntax_pos::Span,
1398                         print_finalizer: bool) -> io::Result<()> {
1399         try!(self.print_ident(ident));
1400         try!(self.print_generics(generics));
1401         if !struct_def.is_struct() {
1402             if struct_def.is_tuple() {
1403                 try!(self.popen());
1404                 try!(self.commasep(
1405                     Inconsistent, struct_def.fields(),
1406                     |s, field| {
1407                         try!(s.maybe_print_comment(field.span.lo));
1408                         try!(s.print_outer_attributes(&field.attrs));
1409                         try!(s.print_visibility(&field.vis));
1410                         s.print_type(&field.ty)
1411                     }
1412                 ));
1413                 try!(self.pclose());
1414             }
1415             try!(self.print_where_clause(&generics.where_clause));
1416             if print_finalizer {
1417                 try!(word(&mut self.s, ";"));
1418             }
1419             try!(self.end());
1420             self.end() // close the outer-box
1421         } else {
1422             try!(self.print_where_clause(&generics.where_clause));
1423             try!(self.nbsp());
1424             try!(self.bopen());
1425             try!(self.hardbreak_if_not_bol());
1426
1427             for field in struct_def.fields() {
1428                 try!(self.hardbreak_if_not_bol());
1429                 try!(self.maybe_print_comment(field.span.lo));
1430                 try!(self.print_outer_attributes(&field.attrs));
1431                 try!(self.print_visibility(&field.vis));
1432                 try!(self.print_ident(field.ident.unwrap()));
1433                 try!(self.word_nbsp(":"));
1434                 try!(self.print_type(&field.ty));
1435                 try!(word(&mut self.s, ","));
1436             }
1437
1438             self.bclose(span)
1439         }
1440     }
1441
1442     /// This doesn't deserve to be called "pretty" printing, but it should be
1443     /// meaning-preserving. A quick hack that might help would be to look at the
1444     /// spans embedded in the TTs to decide where to put spaces and newlines.
1445     /// But it'd be better to parse these according to the grammar of the
1446     /// appropriate macro, transcribe back into the grammar we just parsed from,
1447     /// and then pretty-print the resulting AST nodes (so, e.g., we print
1448     /// expression arguments as expressions). It can be done! I think.
1449     pub fn print_tt(&mut self, tt: &ast::TokenTree) -> io::Result<()> {
1450         match *tt {
1451             TokenTree::Token(_, ref tk) => {
1452                 try!(word(&mut self.s, &token_to_string(tk)));
1453                 match *tk {
1454                     parse::token::DocComment(..) => {
1455                         hardbreak(&mut self.s)
1456                     }
1457                     _ => Ok(())
1458                 }
1459             }
1460             TokenTree::Delimited(_, ref delimed) => {
1461                 try!(word(&mut self.s, &token_to_string(&delimed.open_token())));
1462                 try!(space(&mut self.s));
1463                 try!(self.print_tts(&delimed.tts));
1464                 try!(space(&mut self.s));
1465                 word(&mut self.s, &token_to_string(&delimed.close_token()))
1466             },
1467             TokenTree::Sequence(_, ref seq) => {
1468                 try!(word(&mut self.s, "$("));
1469                 for tt_elt in &seq.tts {
1470                     try!(self.print_tt(tt_elt));
1471                 }
1472                 try!(word(&mut self.s, ")"));
1473                 match seq.separator {
1474                     Some(ref tk) => {
1475                         try!(word(&mut self.s, &token_to_string(tk)));
1476                     }
1477                     None => {},
1478                 }
1479                 match seq.op {
1480                     ast::KleeneOp::ZeroOrMore => word(&mut self.s, "*"),
1481                     ast::KleeneOp::OneOrMore => word(&mut self.s, "+"),
1482                 }
1483             }
1484         }
1485     }
1486
1487     pub fn print_tts(&mut self, tts: &[ast::TokenTree]) -> io::Result<()> {
1488         try!(self.ibox(0));
1489         for (i, tt) in tts.iter().enumerate() {
1490             if i != 0 {
1491                 try!(space(&mut self.s));
1492             }
1493             try!(self.print_tt(tt));
1494         }
1495         self.end()
1496     }
1497
1498     pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> {
1499         try!(self.head(""));
1500         let generics = ast::Generics::default();
1501         try!(self.print_struct(&v.node.data, &generics, v.node.name, v.span, false));
1502         match v.node.disr_expr {
1503             Some(ref d) => {
1504                 try!(space(&mut self.s));
1505                 try!(self.word_space("="));
1506                 self.print_expr(&d)
1507             }
1508             _ => Ok(())
1509         }
1510     }
1511
1512     pub fn print_method_sig(&mut self,
1513                             ident: ast::Ident,
1514                             m: &ast::MethodSig,
1515                             vis: &ast::Visibility)
1516                             -> io::Result<()> {
1517         self.print_fn(&m.decl,
1518                       m.unsafety,
1519                       m.constness,
1520                       m.abi,
1521                       Some(ident),
1522                       &m.generics,
1523                       vis)
1524     }
1525
1526     pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
1527                             -> io::Result<()> {
1528         try!(self.ann.pre(self, NodeSubItem(ti.id)));
1529         try!(self.hardbreak_if_not_bol());
1530         try!(self.maybe_print_comment(ti.span.lo));
1531         try!(self.print_outer_attributes(&ti.attrs));
1532         match ti.node {
1533             ast::TraitItemKind::Const(ref ty, ref default) => {
1534                 try!(self.print_associated_const(ti.ident, &ty,
1535                                             default.as_ref().map(|expr| &**expr),
1536                                             &ast::Visibility::Inherited));
1537             }
1538             ast::TraitItemKind::Method(ref sig, ref body) => {
1539                 if body.is_some() {
1540                     try!(self.head(""));
1541                 }
1542                 try!(self.print_method_sig(ti.ident, sig, &ast::Visibility::Inherited));
1543                 if let Some(ref body) = *body {
1544                     try!(self.nbsp());
1545                     try!(self.print_block_with_attrs(body, &ti.attrs));
1546                 } else {
1547                     try!(word(&mut self.s, ";"));
1548                 }
1549             }
1550             ast::TraitItemKind::Type(ref bounds, ref default) => {
1551                 try!(self.print_associated_type(ti.ident, Some(bounds),
1552                                            default.as_ref().map(|ty| &**ty)));
1553             }
1554             ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
1555                 // code copied from ItemKind::Mac:
1556                 self.print_path(&node.path, false, 0)?;
1557                 word(&mut self.s, "! ")?;
1558                 self.cbox(INDENT_UNIT)?;
1559                 self.popen()?;
1560                 self.print_tts(&node.tts[..])?;
1561                 self.pclose()?;
1562                 word(&mut self.s, ";")?;
1563                 self.end()?
1564             }
1565         }
1566         self.ann.post(self, NodeSubItem(ti.id))
1567     }
1568
1569     pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
1570         try!(self.ann.pre(self, NodeSubItem(ii.id)));
1571         try!(self.hardbreak_if_not_bol());
1572         try!(self.maybe_print_comment(ii.span.lo));
1573         try!(self.print_outer_attributes(&ii.attrs));
1574         if let ast::Defaultness::Default = ii.defaultness {
1575             try!(self.word_nbsp("default"));
1576         }
1577         match ii.node {
1578             ast::ImplItemKind::Const(ref ty, ref expr) => {
1579                 try!(self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis));
1580             }
1581             ast::ImplItemKind::Method(ref sig, ref body) => {
1582                 try!(self.head(""));
1583                 try!(self.print_method_sig(ii.ident, sig, &ii.vis));
1584                 try!(self.nbsp());
1585                 try!(self.print_block_with_attrs(body, &ii.attrs));
1586             }
1587             ast::ImplItemKind::Type(ref ty) => {
1588                 try!(self.print_associated_type(ii.ident, None, Some(ty)));
1589             }
1590             ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
1591                 // code copied from ItemKind::Mac:
1592                 try!(self.print_path(&node.path, false, 0));
1593                 try!(word(&mut self.s, "! "));
1594                 try!(self.cbox(INDENT_UNIT));
1595                 try!(self.popen());
1596                 try!(self.print_tts(&node.tts[..]));
1597                 try!(self.pclose());
1598                 try!(word(&mut self.s, ";"));
1599                 try!(self.end())
1600             }
1601         }
1602         self.ann.post(self, NodeSubItem(ii.id))
1603     }
1604
1605     pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
1606         try!(self.maybe_print_comment(st.span.lo));
1607         match st.node {
1608             ast::StmtKind::Decl(ref decl, _) => {
1609                 try!(self.print_decl(&decl));
1610             }
1611             ast::StmtKind::Expr(ref expr, _) => {
1612                 try!(self.space_if_not_bol());
1613                 try!(self.print_expr_outer_attr_style(&expr, false));
1614             }
1615             ast::StmtKind::Semi(ref expr, _) => {
1616                 try!(self.space_if_not_bol());
1617                 try!(self.print_expr_outer_attr_style(&expr, false));
1618                 try!(word(&mut self.s, ";"));
1619             }
1620             ast::StmtKind::Mac(ref mac, style, ref attrs) => {
1621                 try!(self.space_if_not_bol());
1622                 try!(self.print_outer_attributes(attrs.as_attr_slice()));
1623                 let delim = match style {
1624                     ast::MacStmtStyle::Braces => token::Brace,
1625                     _ => token::Paren
1626                 };
1627                 try!(self.print_mac(&mac, delim));
1628                 match style {
1629                     ast::MacStmtStyle::Braces => {}
1630                     _ => try!(word(&mut self.s, ";")),
1631                 }
1632             }
1633         }
1634         if parse::classify::stmt_ends_with_semi(&st.node) {
1635             try!(word(&mut self.s, ";"));
1636         }
1637         self.maybe_print_trailing_comment(st.span, None)
1638     }
1639
1640     pub fn print_block(&mut self, blk: &ast::Block) -> io::Result<()> {
1641         self.print_block_with_attrs(blk, &[])
1642     }
1643
1644     pub fn print_block_unclosed(&mut self, blk: &ast::Block) -> io::Result<()> {
1645         self.print_block_unclosed_indent(blk, INDENT_UNIT)
1646     }
1647
1648     pub fn print_block_unclosed_with_attrs(&mut self, blk: &ast::Block,
1649                                             attrs: &[ast::Attribute])
1650                                            -> io::Result<()> {
1651         self.print_block_maybe_unclosed(blk, INDENT_UNIT, attrs, false)
1652     }
1653
1654     pub fn print_block_unclosed_indent(&mut self, blk: &ast::Block,
1655                                        indented: usize) -> io::Result<()> {
1656         self.print_block_maybe_unclosed(blk, indented, &[], false)
1657     }
1658
1659     pub fn print_block_with_attrs(&mut self,
1660                                   blk: &ast::Block,
1661                                   attrs: &[ast::Attribute]) -> io::Result<()> {
1662         self.print_block_maybe_unclosed(blk, INDENT_UNIT, attrs, true)
1663     }
1664
1665     pub fn print_block_maybe_unclosed(&mut self,
1666                                       blk: &ast::Block,
1667                                       indented: usize,
1668                                       attrs: &[ast::Attribute],
1669                                       close_box: bool) -> io::Result<()> {
1670         match blk.rules {
1671             BlockCheckMode::Unsafe(..) => try!(self.word_space("unsafe")),
1672             BlockCheckMode::Default => ()
1673         }
1674         try!(self.maybe_print_comment(blk.span.lo));
1675         try!(self.ann.pre(self, NodeBlock(blk)));
1676         try!(self.bopen());
1677
1678         try!(self.print_inner_attributes(attrs));
1679
1680         for st in &blk.stmts {
1681             try!(self.print_stmt(st));
1682         }
1683         match blk.expr {
1684             Some(ref expr) => {
1685                 try!(self.space_if_not_bol());
1686                 try!(self.print_expr_outer_attr_style(&expr, false));
1687                 try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi)));
1688             }
1689             _ => ()
1690         }
1691         try!(self.bclose_maybe_open(blk.span, indented, close_box));
1692         self.ann.post(self, NodeBlock(blk))
1693     }
1694
1695     fn print_else(&mut self, els: Option<&ast::Expr>) -> io::Result<()> {
1696         match els {
1697             Some(_else) => {
1698                 match _else.node {
1699                     // "another else-if"
1700                     ast::ExprKind::If(ref i, ref then, ref e) => {
1701                         try!(self.cbox(INDENT_UNIT - 1));
1702                         try!(self.ibox(0));
1703                         try!(word(&mut self.s, " else if "));
1704                         try!(self.print_expr(&i));
1705                         try!(space(&mut self.s));
1706                         try!(self.print_block(&then));
1707                         self.print_else(e.as_ref().map(|e| &**e))
1708                     }
1709                     // "another else-if-let"
1710                     ast::ExprKind::IfLet(ref pat, ref expr, ref then, ref e) => {
1711                         try!(self.cbox(INDENT_UNIT - 1));
1712                         try!(self.ibox(0));
1713                         try!(word(&mut self.s, " else if let "));
1714                         try!(self.print_pat(&pat));
1715                         try!(space(&mut self.s));
1716                         try!(self.word_space("="));
1717                         try!(self.print_expr(&expr));
1718                         try!(space(&mut self.s));
1719                         try!(self.print_block(&then));
1720                         self.print_else(e.as_ref().map(|e| &**e))
1721                     }
1722                     // "final else"
1723                     ast::ExprKind::Block(ref b) => {
1724                         try!(self.cbox(INDENT_UNIT - 1));
1725                         try!(self.ibox(0));
1726                         try!(word(&mut self.s, " else "));
1727                         self.print_block(&b)
1728                     }
1729                     // BLEAH, constraints would be great here
1730                     _ => {
1731                         panic!("print_if saw if with weird alternative");
1732                     }
1733                 }
1734             }
1735             _ => Ok(())
1736         }
1737     }
1738
1739     pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block,
1740                     elseopt: Option<&ast::Expr>) -> io::Result<()> {
1741         try!(self.head("if"));
1742         try!(self.print_expr(test));
1743         try!(space(&mut self.s));
1744         try!(self.print_block(blk));
1745         self.print_else(elseopt)
1746     }
1747
1748     pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Block,
1749                         elseopt: Option<&ast::Expr>) -> io::Result<()> {
1750         try!(self.head("if let"));
1751         try!(self.print_pat(pat));
1752         try!(space(&mut self.s));
1753         try!(self.word_space("="));
1754         try!(self.print_expr(expr));
1755         try!(space(&mut self.s));
1756         try!(self.print_block(blk));
1757         self.print_else(elseopt)
1758     }
1759
1760     pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
1761                      -> io::Result<()> {
1762         try!(self.print_path(&m.node.path, false, 0));
1763         try!(word(&mut self.s, "!"));
1764         match delim {
1765             token::Paren => try!(self.popen()),
1766             token::Bracket => try!(word(&mut self.s, "[")),
1767             token::Brace => {
1768                 try!(self.head(""));
1769                 try!(self.bopen());
1770             }
1771         }
1772         try!(self.print_tts(&m.node.tts));
1773         match delim {
1774             token::Paren => self.pclose(),
1775             token::Bracket => word(&mut self.s, "]"),
1776             token::Brace => self.bclose(m.span),
1777         }
1778     }
1779
1780
1781     fn print_call_post(&mut self, args: &[P<ast::Expr>]) -> io::Result<()> {
1782         try!(self.popen());
1783         try!(self.commasep_exprs(Inconsistent, args));
1784         self.pclose()
1785     }
1786
1787     pub fn check_expr_bin_needs_paren(&mut self, sub_expr: &ast::Expr,
1788                                       binop: ast::BinOp) -> bool {
1789         match sub_expr.node {
1790             ast::ExprKind::Binary(ref sub_op, _, _) => {
1791                 if AssocOp::from_ast_binop(sub_op.node).precedence() <
1792                     AssocOp::from_ast_binop(binop.node).precedence() {
1793                     true
1794                 } else {
1795                     false
1796                 }
1797             }
1798             _ => true
1799         }
1800     }
1801
1802     pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr) -> io::Result<()> {
1803         let needs_par = needs_parentheses(expr);
1804         if needs_par {
1805             try!(self.popen());
1806         }
1807         try!(self.print_expr(expr));
1808         if needs_par {
1809             try!(self.pclose());
1810         }
1811         Ok(())
1812     }
1813
1814     fn print_expr_in_place(&mut self,
1815                            place: &ast::Expr,
1816                            expr: &ast::Expr) -> io::Result<()> {
1817         try!(self.print_expr_maybe_paren(place));
1818         try!(space(&mut self.s));
1819         try!(self.word_space("<-"));
1820         self.print_expr_maybe_paren(expr)
1821     }
1822
1823     fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>],
1824                       attrs: &[Attribute]) -> io::Result<()> {
1825         try!(self.ibox(INDENT_UNIT));
1826         try!(word(&mut self.s, "["));
1827         try!(self.print_inner_attributes_inline(attrs));
1828         try!(self.commasep_exprs(Inconsistent, &exprs[..]));
1829         try!(word(&mut self.s, "]"));
1830         self.end()
1831     }
1832
1833     fn print_expr_repeat(&mut self,
1834                          element: &ast::Expr,
1835                          count: &ast::Expr,
1836                          attrs: &[Attribute]) -> io::Result<()> {
1837         try!(self.ibox(INDENT_UNIT));
1838         try!(word(&mut self.s, "["));
1839         try!(self.print_inner_attributes_inline(attrs));
1840         try!(self.print_expr(element));
1841         try!(self.word_space(";"));
1842         try!(self.print_expr(count));
1843         try!(word(&mut self.s, "]"));
1844         self.end()
1845     }
1846
1847     fn print_expr_struct(&mut self,
1848                          path: &ast::Path,
1849                          fields: &[ast::Field],
1850                          wth: &Option<P<ast::Expr>>,
1851                          attrs: &[Attribute]) -> io::Result<()> {
1852         try!(self.print_path(path, true, 0));
1853         try!(word(&mut self.s, "{"));
1854         try!(self.print_inner_attributes_inline(attrs));
1855         try!(self.commasep_cmnt(
1856             Consistent,
1857             &fields[..],
1858             |s, field| {
1859                 try!(s.ibox(INDENT_UNIT));
1860                 try!(s.print_ident(field.ident.node));
1861                 try!(s.word_space(":"));
1862                 try!(s.print_expr(&field.expr));
1863                 s.end()
1864             },
1865             |f| f.span));
1866         match *wth {
1867             Some(ref expr) => {
1868                 try!(self.ibox(INDENT_UNIT));
1869                 if !fields.is_empty() {
1870                     try!(word(&mut self.s, ","));
1871                     try!(space(&mut self.s));
1872                 }
1873                 try!(word(&mut self.s, ".."));
1874                 try!(self.print_expr(&expr));
1875                 try!(self.end());
1876             }
1877             _ => if !fields.is_empty() {
1878                 try!(word(&mut self.s, ","))
1879             }
1880         }
1881         try!(word(&mut self.s, "}"));
1882         Ok(())
1883     }
1884
1885     fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>],
1886                       attrs: &[Attribute]) -> io::Result<()> {
1887         try!(self.popen());
1888         try!(self.print_inner_attributes_inline(attrs));
1889         try!(self.commasep_exprs(Inconsistent, &exprs[..]));
1890         if exprs.len() == 1 {
1891             try!(word(&mut self.s, ","));
1892         }
1893         self.pclose()
1894     }
1895
1896     fn print_expr_call(&mut self,
1897                        func: &ast::Expr,
1898                        args: &[P<ast::Expr>]) -> io::Result<()> {
1899         try!(self.print_expr_maybe_paren(func));
1900         self.print_call_post(args)
1901     }
1902
1903     fn print_expr_method_call(&mut self,
1904                               ident: ast::SpannedIdent,
1905                               tys: &[P<ast::Ty>],
1906                               args: &[P<ast::Expr>]) -> io::Result<()> {
1907         let base_args = &args[1..];
1908         try!(self.print_expr(&args[0]));
1909         try!(word(&mut self.s, "."));
1910         try!(self.print_ident(ident.node));
1911         if !tys.is_empty() {
1912             try!(word(&mut self.s, "::<"));
1913             try!(self.commasep(Inconsistent, tys,
1914                           |s, ty| s.print_type(&ty)));
1915             try!(word(&mut self.s, ">"));
1916         }
1917         self.print_call_post(base_args)
1918     }
1919
1920     fn print_expr_binary(&mut self,
1921                          op: ast::BinOp,
1922                          lhs: &ast::Expr,
1923                          rhs: &ast::Expr) -> io::Result<()> {
1924         if self.check_expr_bin_needs_paren(lhs, op) {
1925             try!(self.print_expr_maybe_paren(lhs));
1926         } else {
1927             try!(self.print_expr(lhs));
1928         }
1929         try!(space(&mut self.s));
1930         try!(self.word_space(op.node.to_string()));
1931         if self.check_expr_bin_needs_paren(rhs, op) {
1932             self.print_expr_maybe_paren(rhs)
1933         } else {
1934             self.print_expr(rhs)
1935         }
1936     }
1937
1938     fn print_expr_unary(&mut self,
1939                         op: ast::UnOp,
1940                         expr: &ast::Expr) -> io::Result<()> {
1941         try!(word(&mut self.s, ast::UnOp::to_string(op)));
1942         self.print_expr_maybe_paren(expr)
1943     }
1944
1945     fn print_expr_addr_of(&mut self,
1946                           mutability: ast::Mutability,
1947                           expr: &ast::Expr) -> io::Result<()> {
1948         try!(word(&mut self.s, "&"));
1949         try!(self.print_mutability(mutability));
1950         self.print_expr_maybe_paren(expr)
1951     }
1952
1953     pub fn print_expr(&mut self, expr: &ast::Expr) -> io::Result<()> {
1954         self.print_expr_outer_attr_style(expr, true)
1955     }
1956
1957     fn print_expr_outer_attr_style(&mut self,
1958                                   expr: &ast::Expr,
1959                                   is_inline: bool) -> io::Result<()> {
1960         try!(self.maybe_print_comment(expr.span.lo));
1961
1962         let attrs = expr.attrs.as_attr_slice();
1963         if is_inline {
1964             try!(self.print_outer_attributes_inline(attrs));
1965         } else {
1966             try!(self.print_outer_attributes(attrs));
1967         }
1968
1969         try!(self.ibox(INDENT_UNIT));
1970         try!(self.ann.pre(self, NodeExpr(expr)));
1971         match expr.node {
1972             ast::ExprKind::Box(ref expr) => {
1973                 try!(self.word_space("box"));
1974                 try!(self.print_expr(expr));
1975             }
1976             ast::ExprKind::InPlace(ref place, ref expr) => {
1977                 try!(self.print_expr_in_place(place, expr));
1978             }
1979             ast::ExprKind::Vec(ref exprs) => {
1980                 try!(self.print_expr_vec(&exprs[..], attrs));
1981             }
1982             ast::ExprKind::Repeat(ref element, ref count) => {
1983                 try!(self.print_expr_repeat(&element, &count, attrs));
1984             }
1985             ast::ExprKind::Struct(ref path, ref fields, ref wth) => {
1986                 try!(self.print_expr_struct(path, &fields[..], wth, attrs));
1987             }
1988             ast::ExprKind::Tup(ref exprs) => {
1989                 try!(self.print_expr_tup(&exprs[..], attrs));
1990             }
1991             ast::ExprKind::Call(ref func, ref args) => {
1992                 try!(self.print_expr_call(&func, &args[..]));
1993             }
1994             ast::ExprKind::MethodCall(ident, ref tys, ref args) => {
1995                 try!(self.print_expr_method_call(ident, &tys[..], &args[..]));
1996             }
1997             ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
1998                 try!(self.print_expr_binary(op, &lhs, &rhs));
1999             }
2000             ast::ExprKind::Unary(op, ref expr) => {
2001                 try!(self.print_expr_unary(op, &expr));
2002             }
2003             ast::ExprKind::AddrOf(m, ref expr) => {
2004                 try!(self.print_expr_addr_of(m, &expr));
2005             }
2006             ast::ExprKind::Lit(ref lit) => {
2007                 try!(self.print_literal(&lit));
2008             }
2009             ast::ExprKind::Cast(ref expr, ref ty) => {
2010                 if let ast::ExprKind::Cast(..) = expr.node {
2011                     try!(self.print_expr(&expr));
2012                 } else {
2013                     try!(self.print_expr_maybe_paren(&expr));
2014                 }
2015                 try!(space(&mut self.s));
2016                 try!(self.word_space("as"));
2017                 try!(self.print_type(&ty));
2018             }
2019             ast::ExprKind::Type(ref expr, ref ty) => {
2020                 try!(self.print_expr(&expr));
2021                 try!(self.word_space(":"));
2022                 try!(self.print_type(&ty));
2023             }
2024             ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
2025                 try!(self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e)));
2026             }
2027             ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => {
2028                 try!(self.print_if_let(&pat, &expr, &blk, elseopt.as_ref().map(|e| &**e)));
2029             }
2030             ast::ExprKind::While(ref test, ref blk, opt_ident) => {
2031                 if let Some(ident) = opt_ident {
2032                     try!(self.print_ident(ident.node));
2033                     try!(self.word_space(":"));
2034                 }
2035                 try!(self.head("while"));
2036                 try!(self.print_expr(&test));
2037                 try!(space(&mut self.s));
2038                 try!(self.print_block_with_attrs(&blk, attrs));
2039             }
2040             ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => {
2041                 if let Some(ident) = opt_ident {
2042                     try!(self.print_ident(ident.node));
2043                     try!(self.word_space(":"));
2044                 }
2045                 try!(self.head("while let"));
2046                 try!(self.print_pat(&pat));
2047                 try!(space(&mut self.s));
2048                 try!(self.word_space("="));
2049                 try!(self.print_expr(&expr));
2050                 try!(space(&mut self.s));
2051                 try!(self.print_block_with_attrs(&blk, attrs));
2052             }
2053             ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => {
2054                 if let Some(ident) = opt_ident {
2055                     try!(self.print_ident(ident.node));
2056                     try!(self.word_space(":"));
2057                 }
2058                 try!(self.head("for"));
2059                 try!(self.print_pat(&pat));
2060                 try!(space(&mut self.s));
2061                 try!(self.word_space("in"));
2062                 try!(self.print_expr(&iter));
2063                 try!(space(&mut self.s));
2064                 try!(self.print_block_with_attrs(&blk, attrs));
2065             }
2066             ast::ExprKind::Loop(ref blk, opt_ident) => {
2067                 if let Some(ident) = opt_ident {
2068                     try!(self.print_ident(ident.node));
2069                     try!(self.word_space(":"));
2070                 }
2071                 try!(self.head("loop"));
2072                 try!(space(&mut self.s));
2073                 try!(self.print_block_with_attrs(&blk, attrs));
2074             }
2075             ast::ExprKind::Match(ref expr, ref arms) => {
2076                 try!(self.cbox(INDENT_UNIT));
2077                 try!(self.ibox(4));
2078                 try!(self.word_nbsp("match"));
2079                 try!(self.print_expr(&expr));
2080                 try!(space(&mut self.s));
2081                 try!(self.bopen());
2082                 try!(self.print_inner_attributes_no_trailing_hardbreak(attrs));
2083                 for arm in arms {
2084                     try!(self.print_arm(arm));
2085                 }
2086                 try!(self.bclose_(expr.span, INDENT_UNIT));
2087             }
2088             ast::ExprKind::Closure(capture_clause, ref decl, ref body, _) => {
2089                 try!(self.print_capture_clause(capture_clause));
2090
2091                 try!(self.print_fn_block_args(&decl));
2092                 try!(space(&mut self.s));
2093
2094                 let default_return = match decl.output {
2095                     ast::FunctionRetTy::Default(..) => true,
2096                     _ => false
2097                 };
2098
2099                 if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
2100                     try!(self.print_block_unclosed(&body));
2101                 } else {
2102                     // we extract the block, so as not to create another set of boxes
2103                     let i_expr = body.expr.as_ref().unwrap();
2104                     match i_expr.node {
2105                         ast::ExprKind::Block(ref blk) => {
2106                             try!(self.print_block_unclosed_with_attrs(
2107                                 &blk,
2108                                 i_expr.attrs.as_attr_slice()));
2109                         }
2110                         _ => {
2111                             // this is a bare expression
2112                             try!(self.print_expr(&i_expr));
2113                             try!(self.end()); // need to close a box
2114                         }
2115                     }
2116                 }
2117                 // a box will be closed by print_expr, but we didn't want an overall
2118                 // wrapper so we closed the corresponding opening. so create an
2119                 // empty box to satisfy the close.
2120                 try!(self.ibox(0));
2121             }
2122             ast::ExprKind::Block(ref blk) => {
2123                 // containing cbox, will be closed by print-block at }
2124                 try!(self.cbox(INDENT_UNIT));
2125                 // head-box, will be closed by print-block after {
2126                 try!(self.ibox(0));
2127                 try!(self.print_block_with_attrs(&blk, attrs));
2128             }
2129             ast::ExprKind::Assign(ref lhs, ref rhs) => {
2130                 try!(self.print_expr(&lhs));
2131                 try!(space(&mut self.s));
2132                 try!(self.word_space("="));
2133                 try!(self.print_expr(&rhs));
2134             }
2135             ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
2136                 try!(self.print_expr(&lhs));
2137                 try!(space(&mut self.s));
2138                 try!(word(&mut self.s, op.node.to_string()));
2139                 try!(self.word_space("="));
2140                 try!(self.print_expr(&rhs));
2141             }
2142             ast::ExprKind::Field(ref expr, id) => {
2143                 try!(self.print_expr(&expr));
2144                 try!(word(&mut self.s, "."));
2145                 try!(self.print_ident(id.node));
2146             }
2147             ast::ExprKind::TupField(ref expr, id) => {
2148                 try!(self.print_expr(&expr));
2149                 try!(word(&mut self.s, "."));
2150                 try!(self.print_usize(id.node));
2151             }
2152             ast::ExprKind::Index(ref expr, ref index) => {
2153                 try!(self.print_expr(&expr));
2154                 try!(word(&mut self.s, "["));
2155                 try!(self.print_expr(&index));
2156                 try!(word(&mut self.s, "]"));
2157             }
2158             ast::ExprKind::Range(ref start, ref end, limits) => {
2159                 if let &Some(ref e) = start {
2160                     try!(self.print_expr(&e));
2161                 }
2162                 if limits == ast::RangeLimits::HalfOpen {
2163                     try!(word(&mut self.s, ".."));
2164                 } else {
2165                     try!(word(&mut self.s, "..."));
2166                 }
2167                 if let &Some(ref e) = end {
2168                     try!(self.print_expr(&e));
2169                 }
2170             }
2171             ast::ExprKind::Path(None, ref path) => {
2172                 try!(self.print_path(path, true, 0))
2173             }
2174             ast::ExprKind::Path(Some(ref qself), ref path) => {
2175                 try!(self.print_qpath(path, qself, true))
2176             }
2177             ast::ExprKind::Break(opt_ident) => {
2178                 try!(word(&mut self.s, "break"));
2179                 try!(space(&mut self.s));
2180                 if let Some(ident) = opt_ident {
2181                     try!(self.print_ident(ident.node));
2182                     try!(space(&mut self.s));
2183                 }
2184             }
2185             ast::ExprKind::Again(opt_ident) => {
2186                 try!(word(&mut self.s, "continue"));
2187                 try!(space(&mut self.s));
2188                 if let Some(ident) = opt_ident {
2189                     try!(self.print_ident(ident.node));
2190                     try!(space(&mut self.s))
2191                 }
2192             }
2193             ast::ExprKind::Ret(ref result) => {
2194                 try!(word(&mut self.s, "return"));
2195                 match *result {
2196                     Some(ref expr) => {
2197                         try!(word(&mut self.s, " "));
2198                         try!(self.print_expr(&expr));
2199                     }
2200                     _ => ()
2201                 }
2202             }
2203             ast::ExprKind::InlineAsm(ref a) => {
2204                 try!(word(&mut self.s, "asm!"));
2205                 try!(self.popen());
2206                 try!(self.print_string(&a.asm, a.asm_str_style));
2207                 try!(self.word_space(":"));
2208
2209                 try!(self.commasep(Inconsistent, &a.outputs,
2210                                    |s, out| {
2211                     let mut ch = out.constraint.chars();
2212                     match ch.next() {
2213                         Some('=') if out.is_rw => {
2214                             try!(s.print_string(&format!("+{}", ch.as_str()),
2215                                            ast::StrStyle::Cooked))
2216                         }
2217                         _ => try!(s.print_string(&out.constraint,
2218                                             ast::StrStyle::Cooked))
2219                     }
2220                     try!(s.popen());
2221                     try!(s.print_expr(&out.expr));
2222                     try!(s.pclose());
2223                     Ok(())
2224                 }));
2225                 try!(space(&mut self.s));
2226                 try!(self.word_space(":"));
2227
2228                 try!(self.commasep(Inconsistent, &a.inputs,
2229                                    |s, &(ref co, ref o)| {
2230                     try!(s.print_string(&co, ast::StrStyle::Cooked));
2231                     try!(s.popen());
2232                     try!(s.print_expr(&o));
2233                     try!(s.pclose());
2234                     Ok(())
2235                 }));
2236                 try!(space(&mut self.s));
2237                 try!(self.word_space(":"));
2238
2239                 try!(self.commasep(Inconsistent, &a.clobbers,
2240                                    |s, co| {
2241                     try!(s.print_string(&co, ast::StrStyle::Cooked));
2242                     Ok(())
2243                 }));
2244
2245                 let mut options = vec!();
2246                 if a.volatile {
2247                     options.push("volatile");
2248                 }
2249                 if a.alignstack {
2250                     options.push("alignstack");
2251                 }
2252                 if a.dialect == ast::AsmDialect::Intel {
2253                     options.push("intel");
2254                 }
2255
2256                 if !options.is_empty() {
2257                     try!(space(&mut self.s));
2258                     try!(self.word_space(":"));
2259                     try!(self.commasep(Inconsistent, &options,
2260                                   |s, &co| {
2261                                       try!(s.print_string(co, ast::StrStyle::Cooked));
2262                                       Ok(())
2263                                   }));
2264                 }
2265
2266                 try!(self.pclose());
2267             }
2268             ast::ExprKind::Mac(ref m) => try!(self.print_mac(m, token::Paren)),
2269             ast::ExprKind::Paren(ref e) => {
2270                 try!(self.popen());
2271                 try!(self.print_inner_attributes_inline(attrs));
2272                 try!(self.print_expr(&e));
2273                 try!(self.pclose());
2274             },
2275             ast::ExprKind::Try(ref e) => {
2276                 try!(self.print_expr(e));
2277                 try!(word(&mut self.s, "?"))
2278             }
2279         }
2280         try!(self.ann.post(self, NodeExpr(expr)));
2281         self.end()
2282     }
2283
2284     pub fn print_local_decl(&mut self, loc: &ast::Local) -> io::Result<()> {
2285         try!(self.print_pat(&loc.pat));
2286         if let Some(ref ty) = loc.ty {
2287             try!(self.word_space(":"));
2288             try!(self.print_type(&ty));
2289         }
2290         Ok(())
2291     }
2292
2293     pub fn print_decl(&mut self, decl: &ast::Decl) -> io::Result<()> {
2294         try!(self.maybe_print_comment(decl.span.lo));
2295         match decl.node {
2296             ast::DeclKind::Local(ref loc) => {
2297                 try!(self.print_outer_attributes(loc.attrs.as_attr_slice()));
2298                 try!(self.space_if_not_bol());
2299                 try!(self.ibox(INDENT_UNIT));
2300                 try!(self.word_nbsp("let"));
2301
2302                 try!(self.ibox(INDENT_UNIT));
2303                 try!(self.print_local_decl(&loc));
2304                 try!(self.end());
2305                 if let Some(ref init) = loc.init {
2306                     try!(self.nbsp());
2307                     try!(self.word_space("="));
2308                     try!(self.print_expr(&init));
2309                 }
2310                 self.end()
2311             }
2312             ast::DeclKind::Item(ref item) => self.print_item(&item)
2313         }
2314     }
2315
2316     pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
2317         try!(word(&mut self.s, &ident.name.as_str()));
2318         self.ann.post(self, NodeIdent(&ident))
2319     }
2320
2321     pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
2322         word(&mut self.s, &i.to_string())
2323     }
2324
2325     pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
2326         try!(word(&mut self.s, &name.as_str()));
2327         self.ann.post(self, NodeName(&name))
2328     }
2329
2330     pub fn print_for_decl(&mut self, loc: &ast::Local,
2331                           coll: &ast::Expr) -> io::Result<()> {
2332         try!(self.print_local_decl(loc));
2333         try!(space(&mut self.s));
2334         try!(self.word_space("in"));
2335         self.print_expr(coll)
2336     }
2337
2338     fn print_path(&mut self,
2339                   path: &ast::Path,
2340                   colons_before_params: bool,
2341                   depth: usize)
2342                   -> io::Result<()>
2343     {
2344         try!(self.maybe_print_comment(path.span.lo));
2345
2346         let mut first = !path.global;
2347         for segment in &path.segments[..path.segments.len()-depth] {
2348             if first {
2349                 first = false
2350             } else {
2351                 try!(word(&mut self.s, "::"))
2352             }
2353
2354             try!(self.print_ident(segment.identifier));
2355
2356             try!(self.print_path_parameters(&segment.parameters, colons_before_params));
2357         }
2358
2359         Ok(())
2360     }
2361
2362     fn print_qpath(&mut self,
2363                    path: &ast::Path,
2364                    qself: &ast::QSelf,
2365                    colons_before_params: bool)
2366                    -> io::Result<()>
2367     {
2368         try!(word(&mut self.s, "<"));
2369         try!(self.print_type(&qself.ty));
2370         if qself.position > 0 {
2371             try!(space(&mut self.s));
2372             try!(self.word_space("as"));
2373             let depth = path.segments.len() - qself.position;
2374             try!(self.print_path(&path, false, depth));
2375         }
2376         try!(word(&mut self.s, ">"));
2377         try!(word(&mut self.s, "::"));
2378         let item_segment = path.segments.last().unwrap();
2379         try!(self.print_ident(item_segment.identifier));
2380         self.print_path_parameters(&item_segment.parameters, colons_before_params)
2381     }
2382
2383     fn print_path_parameters(&mut self,
2384                              parameters: &ast::PathParameters,
2385                              colons_before_params: bool)
2386                              -> io::Result<()>
2387     {
2388         if parameters.is_empty() {
2389             return Ok(());
2390         }
2391
2392         if colons_before_params {
2393             try!(word(&mut self.s, "::"))
2394         }
2395
2396         match *parameters {
2397             ast::PathParameters::AngleBracketed(ref data) => {
2398                 try!(word(&mut self.s, "<"));
2399
2400                 let mut comma = false;
2401                 for lifetime in &data.lifetimes {
2402                     if comma {
2403                         try!(self.word_space(","))
2404                     }
2405                     try!(self.print_lifetime(lifetime));
2406                     comma = true;
2407                 }
2408
2409                 if !data.types.is_empty() {
2410                     if comma {
2411                         try!(self.word_space(","))
2412                     }
2413                     try!(self.commasep(
2414                         Inconsistent,
2415                         &data.types,
2416                         |s, ty| s.print_type(&ty)));
2417                         comma = true;
2418                 }
2419
2420                 for binding in data.bindings.iter() {
2421                     if comma {
2422                         try!(self.word_space(","))
2423                     }
2424                     try!(self.print_ident(binding.ident));
2425                     try!(space(&mut self.s));
2426                     try!(self.word_space("="));
2427                     try!(self.print_type(&binding.ty));
2428                     comma = true;
2429                 }
2430
2431                 try!(word(&mut self.s, ">"))
2432             }
2433
2434             ast::PathParameters::Parenthesized(ref data) => {
2435                 try!(word(&mut self.s, "("));
2436                 try!(self.commasep(
2437                     Inconsistent,
2438                     &data.inputs,
2439                     |s, ty| s.print_type(&ty)));
2440                 try!(word(&mut self.s, ")"));
2441
2442                 match data.output {
2443                     None => { }
2444                     Some(ref ty) => {
2445                         try!(self.space_if_not_bol());
2446                         try!(self.word_space("->"));
2447                         try!(self.print_type(&ty));
2448                     }
2449                 }
2450             }
2451         }
2452
2453         Ok(())
2454     }
2455
2456     pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
2457         try!(self.maybe_print_comment(pat.span.lo));
2458         try!(self.ann.pre(self, NodePat(pat)));
2459         /* Pat isn't normalized, but the beauty of it
2460          is that it doesn't matter */
2461         match pat.node {
2462             PatKind::Wild => try!(word(&mut self.s, "_")),
2463             PatKind::Ident(binding_mode, ref path1, ref sub) => {
2464                 match binding_mode {
2465                     ast::BindingMode::ByRef(mutbl) => {
2466                         try!(self.word_nbsp("ref"));
2467                         try!(self.print_mutability(mutbl));
2468                     }
2469                     ast::BindingMode::ByValue(ast::Mutability::Immutable) => {}
2470                     ast::BindingMode::ByValue(ast::Mutability::Mutable) => {
2471                         try!(self.word_nbsp("mut"));
2472                     }
2473                 }
2474                 try!(self.print_ident(path1.node));
2475                 if let Some(ref p) = *sub {
2476                     try!(word(&mut self.s, "@"));
2477                     try!(self.print_pat(&p));
2478                 }
2479             }
2480             PatKind::TupleStruct(ref path, ref elts, ddpos) => {
2481                 try!(self.print_path(path, true, 0));
2482                 try!(self.popen());
2483                 if let Some(ddpos) = ddpos {
2484                     try!(self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)));
2485                     if ddpos != 0 {
2486                         try!(self.word_space(","));
2487                     }
2488                     try!(word(&mut self.s, ".."));
2489                     if ddpos != elts.len() {
2490                         try!(word(&mut self.s, ","));
2491                         try!(self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)));
2492                     }
2493                 } else {
2494                     try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)));
2495                 }
2496                 try!(self.pclose());
2497             }
2498             PatKind::Path(None, ref path) => {
2499                 try!(self.print_path(path, true, 0));
2500             }
2501             PatKind::Path(Some(ref qself), ref path) => {
2502                 try!(self.print_qpath(path, qself, false));
2503             }
2504             PatKind::Struct(ref path, ref fields, etc) => {
2505                 try!(self.print_path(path, true, 0));
2506                 try!(self.nbsp());
2507                 try!(self.word_space("{"));
2508                 try!(self.commasep_cmnt(
2509                     Consistent, &fields[..],
2510                     |s, f| {
2511                         try!(s.cbox(INDENT_UNIT));
2512                         if !f.node.is_shorthand {
2513                             try!(s.print_ident(f.node.ident));
2514                             try!(s.word_nbsp(":"));
2515                         }
2516                         try!(s.print_pat(&f.node.pat));
2517                         s.end()
2518                     },
2519                     |f| f.node.pat.span));
2520                 if etc {
2521                     if !fields.is_empty() { try!(self.word_space(",")); }
2522                     try!(word(&mut self.s, ".."));
2523                 }
2524                 try!(space(&mut self.s));
2525                 try!(word(&mut self.s, "}"));
2526             }
2527             PatKind::Tuple(ref elts, ddpos) => {
2528                 try!(self.popen());
2529                 if let Some(ddpos) = ddpos {
2530                     try!(self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)));
2531                     if ddpos != 0 {
2532                         try!(self.word_space(","));
2533                     }
2534                     try!(word(&mut self.s, ".."));
2535                     if ddpos != elts.len() {
2536                         try!(word(&mut self.s, ","));
2537                         try!(self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)));
2538                     }
2539                 } else {
2540                     try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)));
2541                     if elts.len() == 1 {
2542                         try!(word(&mut self.s, ","));
2543                     }
2544                 }
2545                 try!(self.pclose());
2546             }
2547             PatKind::Box(ref inner) => {
2548                 try!(word(&mut self.s, "box "));
2549                 try!(self.print_pat(&inner));
2550             }
2551             PatKind::Ref(ref inner, mutbl) => {
2552                 try!(word(&mut self.s, "&"));
2553                 if mutbl == ast::Mutability::Mutable {
2554                     try!(word(&mut self.s, "mut "));
2555                 }
2556                 try!(self.print_pat(&inner));
2557             }
2558             PatKind::Lit(ref e) => try!(self.print_expr(&**e)),
2559             PatKind::Range(ref begin, ref end) => {
2560                 try!(self.print_expr(&begin));
2561                 try!(space(&mut self.s));
2562                 try!(word(&mut self.s, "..."));
2563                 try!(self.print_expr(&end));
2564             }
2565             PatKind::Vec(ref before, ref slice, ref after) => {
2566                 try!(word(&mut self.s, "["));
2567                 try!(self.commasep(Inconsistent,
2568                                    &before[..],
2569                                    |s, p| s.print_pat(&p)));
2570                 if let Some(ref p) = *slice {
2571                     if !before.is_empty() { try!(self.word_space(",")); }
2572                     if p.node != PatKind::Wild {
2573                         try!(self.print_pat(&p));
2574                     }
2575                     try!(word(&mut self.s, ".."));
2576                     if !after.is_empty() { try!(self.word_space(",")); }
2577                 }
2578                 try!(self.commasep(Inconsistent,
2579                                    &after[..],
2580                                    |s, p| s.print_pat(&p)));
2581                 try!(word(&mut self.s, "]"));
2582             }
2583             PatKind::Mac(ref m) => try!(self.print_mac(m, token::Paren)),
2584         }
2585         self.ann.post(self, NodePat(pat))
2586     }
2587
2588     fn print_arm(&mut self, arm: &ast::Arm) -> io::Result<()> {
2589         // I have no idea why this check is necessary, but here it
2590         // is :(
2591         if arm.attrs.is_empty() {
2592             try!(space(&mut self.s));
2593         }
2594         try!(self.cbox(INDENT_UNIT));
2595         try!(self.ibox(0));
2596         try!(self.print_outer_attributes(&arm.attrs));
2597         let mut first = true;
2598         for p in &arm.pats {
2599             if first {
2600                 first = false;
2601             } else {
2602                 try!(space(&mut self.s));
2603                 try!(self.word_space("|"));
2604             }
2605             try!(self.print_pat(&p));
2606         }
2607         try!(space(&mut self.s));
2608         if let Some(ref e) = arm.guard {
2609             try!(self.word_space("if"));
2610             try!(self.print_expr(&e));
2611             try!(space(&mut self.s));
2612         }
2613         try!(self.word_space("=>"));
2614
2615         match arm.body.node {
2616             ast::ExprKind::Block(ref blk) => {
2617                 // the block will close the pattern's ibox
2618                 try!(self.print_block_unclosed_indent(&blk, INDENT_UNIT));
2619
2620                 // If it is a user-provided unsafe block, print a comma after it
2621                 if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
2622                     try!(word(&mut self.s, ","));
2623                 }
2624             }
2625             _ => {
2626                 try!(self.end()); // close the ibox for the pattern
2627                 try!(self.print_expr(&arm.body));
2628                 try!(word(&mut self.s, ","));
2629             }
2630         }
2631         self.end() // close enclosing cbox
2632     }
2633
2634     fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) -> io::Result<()> {
2635         match explicit_self.node {
2636             SelfKind::Value(m) => {
2637                 try!(self.print_mutability(m));
2638                 word(&mut self.s, "self")
2639             }
2640             SelfKind::Region(ref lt, m) => {
2641                 try!(word(&mut self.s, "&"));
2642                 try!(self.print_opt_lifetime(lt));
2643                 try!(self.print_mutability(m));
2644                 word(&mut self.s, "self")
2645             }
2646             SelfKind::Explicit(ref typ, m) => {
2647                 try!(self.print_mutability(m));
2648                 try!(word(&mut self.s, "self"));
2649                 try!(self.word_space(":"));
2650                 self.print_type(&typ)
2651             }
2652         }
2653     }
2654
2655     pub fn print_fn(&mut self,
2656                     decl: &ast::FnDecl,
2657                     unsafety: ast::Unsafety,
2658                     constness: ast::Constness,
2659                     abi: abi::Abi,
2660                     name: Option<ast::Ident>,
2661                     generics: &ast::Generics,
2662                     vis: &ast::Visibility) -> io::Result<()> {
2663         try!(self.print_fn_header_info(unsafety, constness, abi, vis));
2664
2665         if let Some(name) = name {
2666             try!(self.nbsp());
2667             try!(self.print_ident(name));
2668         }
2669         try!(self.print_generics(generics));
2670         try!(self.print_fn_args_and_ret(decl));
2671         self.print_where_clause(&generics.where_clause)
2672     }
2673
2674     pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl)
2675         -> io::Result<()> {
2676         try!(self.popen());
2677         try!(self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false)));
2678         if decl.variadic {
2679             try!(word(&mut self.s, ", ..."));
2680         }
2681         try!(self.pclose());
2682
2683         self.print_fn_output(decl)
2684     }
2685
2686     pub fn print_fn_block_args(
2687             &mut self,
2688             decl: &ast::FnDecl)
2689             -> io::Result<()> {
2690         try!(word(&mut self.s, "|"));
2691         try!(self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true)));
2692         try!(word(&mut self.s, "|"));
2693
2694         if let ast::FunctionRetTy::Default(..) = decl.output {
2695             return Ok(());
2696         }
2697
2698         try!(self.space_if_not_bol());
2699         try!(self.word_space("->"));
2700         match decl.output {
2701             ast::FunctionRetTy::Ty(ref ty) => {
2702                 try!(self.print_type(&ty));
2703                 self.maybe_print_comment(ty.span.lo)
2704             }
2705             ast::FunctionRetTy::Default(..) => unreachable!(),
2706             ast::FunctionRetTy::None(span) => {
2707                 try!(self.word_nbsp("!"));
2708                 self.maybe_print_comment(span.lo)
2709             }
2710         }
2711     }
2712
2713     pub fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy)
2714                                 -> io::Result<()> {
2715         match capture_clause {
2716             ast::CaptureBy::Value => self.word_space("move"),
2717             ast::CaptureBy::Ref => Ok(()),
2718         }
2719     }
2720
2721     pub fn print_bounds(&mut self,
2722                         prefix: &str,
2723                         bounds: &[ast::TyParamBound])
2724                         -> io::Result<()> {
2725         if !bounds.is_empty() {
2726             try!(word(&mut self.s, prefix));
2727             let mut first = true;
2728             for bound in bounds {
2729                 try!(self.nbsp());
2730                 if first {
2731                     first = false;
2732                 } else {
2733                     try!(self.word_space("+"));
2734                 }
2735
2736                 try!(match *bound {
2737                     TraitTyParamBound(ref tref, TraitBoundModifier::None) => {
2738                         self.print_poly_trait_ref(tref)
2739                     }
2740                     TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => {
2741                         try!(word(&mut self.s, "?"));
2742                         self.print_poly_trait_ref(tref)
2743                     }
2744                     RegionTyParamBound(ref lt) => {
2745                         self.print_lifetime(lt)
2746                     }
2747                 })
2748             }
2749             Ok(())
2750         } else {
2751             Ok(())
2752         }
2753     }
2754
2755     pub fn print_lifetime(&mut self,
2756                           lifetime: &ast::Lifetime)
2757                           -> io::Result<()>
2758     {
2759         self.print_name(lifetime.name)
2760     }
2761
2762     pub fn print_lifetime_def(&mut self,
2763                               lifetime: &ast::LifetimeDef)
2764                               -> io::Result<()>
2765     {
2766         try!(self.print_lifetime(&lifetime.lifetime));
2767         let mut sep = ":";
2768         for v in &lifetime.bounds {
2769             try!(word(&mut self.s, sep));
2770             try!(self.print_lifetime(v));
2771             sep = "+";
2772         }
2773         Ok(())
2774     }
2775
2776     pub fn print_generics(&mut self,
2777                           generics: &ast::Generics)
2778                           -> io::Result<()>
2779     {
2780         let total = generics.lifetimes.len() + generics.ty_params.len();
2781         if total == 0 {
2782             return Ok(());
2783         }
2784
2785         try!(word(&mut self.s, "<"));
2786
2787         let mut ints = Vec::new();
2788         for i in 0..total {
2789             ints.push(i);
2790         }
2791
2792         try!(self.commasep(Inconsistent, &ints[..], |s, &idx| {
2793             if idx < generics.lifetimes.len() {
2794                 let lifetime = &generics.lifetimes[idx];
2795                 s.print_lifetime_def(lifetime)
2796             } else {
2797                 let idx = idx - generics.lifetimes.len();
2798                 let param = &generics.ty_params[idx];
2799                 s.print_ty_param(param)
2800             }
2801         }));
2802
2803         try!(word(&mut self.s, ">"));
2804         Ok(())
2805     }
2806
2807     pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> {
2808         try!(self.print_ident(param.ident));
2809         try!(self.print_bounds(":", &param.bounds));
2810         match param.default {
2811             Some(ref default) => {
2812                 try!(space(&mut self.s));
2813                 try!(self.word_space("="));
2814                 self.print_type(&default)
2815             }
2816             _ => Ok(())
2817         }
2818     }
2819
2820     pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
2821                               -> io::Result<()> {
2822         if where_clause.predicates.is_empty() {
2823             return Ok(())
2824         }
2825
2826         try!(space(&mut self.s));
2827         try!(self.word_space("where"));
2828
2829         for (i, predicate) in where_clause.predicates.iter().enumerate() {
2830             if i != 0 {
2831                 try!(self.word_space(","));
2832             }
2833
2834             match *predicate {
2835                 ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes,
2836                                                                              ref bounded_ty,
2837                                                                              ref bounds,
2838                                                                              ..}) => {
2839                     try!(self.print_formal_lifetime_list(bound_lifetimes));
2840                     try!(self.print_type(&bounded_ty));
2841                     try!(self.print_bounds(":", bounds));
2842                 }
2843                 ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
2844                                                                                ref bounds,
2845                                                                                ..}) => {
2846                     try!(self.print_lifetime(lifetime));
2847                     try!(word(&mut self.s, ":"));
2848
2849                     for (i, bound) in bounds.iter().enumerate() {
2850                         try!(self.print_lifetime(bound));
2851
2852                         if i != 0 {
2853                             try!(word(&mut self.s, ":"));
2854                         }
2855                     }
2856                 }
2857                 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
2858                     try!(self.print_path(path, false, 0));
2859                     try!(space(&mut self.s));
2860                     try!(self.word_space("="));
2861                     try!(self.print_type(&ty));
2862                 }
2863             }
2864         }
2865
2866         Ok(())
2867     }
2868
2869     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
2870         match vp.node {
2871             ast::ViewPathSimple(ident, ref path) => {
2872                 try!(self.print_path(path, false, 0));
2873
2874                 if path.segments.last().unwrap().identifier.name !=
2875                         ident.name {
2876                     try!(space(&mut self.s));
2877                     try!(self.word_space("as"));
2878                     try!(self.print_ident(ident));
2879                 }
2880
2881                 Ok(())
2882             }
2883
2884             ast::ViewPathGlob(ref path) => {
2885                 try!(self.print_path(path, false, 0));
2886                 word(&mut self.s, "::*")
2887             }
2888
2889             ast::ViewPathList(ref path, ref idents) => {
2890                 if path.segments.is_empty() {
2891                     try!(word(&mut self.s, "{"));
2892                 } else {
2893                     try!(self.print_path(path, false, 0));
2894                     try!(word(&mut self.s, "::{"));
2895                 }
2896                 try!(self.commasep(Inconsistent, &idents[..], |s, w| {
2897                     match w.node {
2898                         ast::PathListItemKind::Ident { name, rename, .. } => {
2899                             try!(s.print_ident(name));
2900                             if let Some(ident) = rename {
2901                                 try!(space(&mut s.s));
2902                                 try!(s.word_space("as"));
2903                                 try!(s.print_ident(ident));
2904                             }
2905                             Ok(())
2906                         },
2907                         ast::PathListItemKind::Mod { rename, .. } => {
2908                             try!(word(&mut s.s, "self"));
2909                             if let Some(ident) = rename {
2910                                 try!(space(&mut s.s));
2911                                 try!(s.word_space("as"));
2912                                 try!(s.print_ident(ident));
2913                             }
2914                             Ok(())
2915                         }
2916                     }
2917                 }));
2918                 word(&mut self.s, "}")
2919             }
2920         }
2921     }
2922
2923     pub fn print_mutability(&mut self,
2924                             mutbl: ast::Mutability) -> io::Result<()> {
2925         match mutbl {
2926             ast::Mutability::Mutable => self.word_nbsp("mut"),
2927             ast::Mutability::Immutable => Ok(()),
2928         }
2929     }
2930
2931     pub fn print_mt(&mut self, mt: &ast::MutTy) -> io::Result<()> {
2932         try!(self.print_mutability(mt.mutbl));
2933         self.print_type(&mt.ty)
2934     }
2935
2936     pub fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) -> io::Result<()> {
2937         try!(self.ibox(INDENT_UNIT));
2938         match input.ty.node {
2939             ast::TyKind::Infer if is_closure => try!(self.print_pat(&input.pat)),
2940             _ => {
2941                 if let Some(eself) = input.to_self() {
2942                     try!(self.print_explicit_self(&eself));
2943                 } else {
2944                     let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node {
2945                         ident.node.name == keywords::Invalid.name()
2946                     } else {
2947                         false
2948                     };
2949                     if !invalid {
2950                         try!(self.print_pat(&input.pat));
2951                         try!(word(&mut self.s, ":"));
2952                         try!(space(&mut self.s));
2953                     }
2954                     try!(self.print_type(&input.ty));
2955                 }
2956             }
2957         }
2958         self.end()
2959     }
2960
2961     pub fn print_fn_output(&mut self, decl: &ast::FnDecl) -> io::Result<()> {
2962         if let ast::FunctionRetTy::Default(..) = decl.output {
2963             return Ok(());
2964         }
2965
2966         try!(self.space_if_not_bol());
2967         try!(self.ibox(INDENT_UNIT));
2968         try!(self.word_space("->"));
2969         match decl.output {
2970             ast::FunctionRetTy::None(_) =>
2971                 try!(self.word_nbsp("!")),
2972             ast::FunctionRetTy::Default(..) => unreachable!(),
2973             ast::FunctionRetTy::Ty(ref ty) =>
2974                 try!(self.print_type(&ty))
2975         }
2976         try!(self.end());
2977
2978         match decl.output {
2979             ast::FunctionRetTy::Ty(ref output) => self.maybe_print_comment(output.span.lo),
2980             _ => Ok(())
2981         }
2982     }
2983
2984     pub fn print_ty_fn(&mut self,
2985                        abi: abi::Abi,
2986                        unsafety: ast::Unsafety,
2987                        decl: &ast::FnDecl,
2988                        name: Option<ast::Ident>,
2989                        generics: &ast::Generics)
2990                        -> io::Result<()> {
2991         try!(self.ibox(INDENT_UNIT));
2992         if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
2993             try!(word(&mut self.s, "for"));
2994             try!(self.print_generics(generics));
2995         }
2996         let generics = ast::Generics {
2997             lifetimes: Vec::new(),
2998             ty_params: P::new(),
2999             where_clause: ast::WhereClause {
3000                 id: ast::DUMMY_NODE_ID,
3001                 predicates: Vec::new(),
3002             },
3003         };
3004         try!(self.print_fn(decl,
3005                       unsafety,
3006                       ast::Constness::NotConst,
3007                       abi,
3008                       name,
3009                       &generics,
3010                       &ast::Visibility::Inherited));
3011         self.end()
3012     }
3013
3014     pub fn maybe_print_trailing_comment(&mut self, span: syntax_pos::Span,
3015                                         next_pos: Option<BytePos>)
3016         -> io::Result<()> {
3017         let cm = match self.cm {
3018             Some(cm) => cm,
3019             _ => return Ok(())
3020         };
3021         if let Some(ref cmnt) = self.next_comment() {
3022             if (*cmnt).style != comments::Trailing { return Ok(()) }
3023             let span_line = cm.lookup_char_pos(span.hi);
3024             let comment_line = cm.lookup_char_pos((*cmnt).pos);
3025             let mut next = (*cmnt).pos + BytePos(1);
3026             if let Some(p) = next_pos {
3027                 next = p;
3028             }
3029             if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
3030                span_line.line == comment_line.line {
3031                 self.print_comment(cmnt)?;
3032                 self.cur_cmnt_and_lit.cur_cmnt += 1;
3033             }
3034         }
3035         Ok(())
3036     }
3037
3038     pub fn print_remaining_comments(&mut self) -> io::Result<()> {
3039         // If there aren't any remaining comments, then we need to manually
3040         // make sure there is a line break at the end.
3041         if self.next_comment().is_none() {
3042             try!(hardbreak(&mut self.s));
3043         }
3044         loop {
3045             match self.next_comment() {
3046                 Some(ref cmnt) => {
3047                     try!(self.print_comment(cmnt));
3048                     self.cur_cmnt_and_lit.cur_cmnt += 1;
3049                 }
3050                 _ => break
3051             }
3052         }
3053         Ok(())
3054     }
3055
3056     pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
3057                                                   opt_abi: Option<Abi>)
3058         -> io::Result<()> {
3059         match opt_abi {
3060             Some(Abi::Rust) => Ok(()),
3061             Some(abi) => {
3062                 try!(self.word_nbsp("extern"));
3063                 self.word_nbsp(&abi.to_string())
3064             }
3065             None => Ok(())
3066         }
3067     }
3068
3069     pub fn print_extern_opt_abi(&mut self,
3070                                 opt_abi: Option<Abi>) -> io::Result<()> {
3071         match opt_abi {
3072             Some(abi) => {
3073                 try!(self.word_nbsp("extern"));
3074                 self.word_nbsp(&abi.to_string())
3075             }
3076             None => Ok(())
3077         }
3078     }
3079
3080     pub fn print_fn_header_info(&mut self,
3081                                 unsafety: ast::Unsafety,
3082                                 constness: ast::Constness,
3083                                 abi: Abi,
3084                                 vis: &ast::Visibility) -> io::Result<()> {
3085         try!(word(&mut self.s, &visibility_qualified(vis, "")));
3086
3087         match constness {
3088             ast::Constness::NotConst => {}
3089             ast::Constness::Const => try!(self.word_nbsp("const"))
3090         }
3091
3092         try!(self.print_unsafety(unsafety));
3093
3094         if abi != Abi::Rust {
3095             try!(self.word_nbsp("extern"));
3096             try!(self.word_nbsp(&abi.to_string()));
3097         }
3098
3099         word(&mut self.s, "fn")
3100     }
3101
3102     pub fn print_unsafety(&mut self, s: ast::Unsafety) -> io::Result<()> {
3103         match s {
3104             ast::Unsafety::Normal => Ok(()),
3105             ast::Unsafety::Unsafe => self.word_nbsp("unsafe"),
3106         }
3107     }
3108 }
3109
3110 fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() }
3111
3112 #[cfg(test)]
3113 mod tests {
3114     use super::*;
3115
3116     use ast;
3117     use codemap;
3118     use parse::token;
3119     use syntax_pos;
3120
3121     #[test]
3122     fn test_fun_to_string() {
3123         let abba_ident = token::str_to_ident("abba");
3124
3125         let decl = ast::FnDecl {
3126             inputs: Vec::new(),
3127             output: ast::FunctionRetTy::Default(syntax_pos::DUMMY_SP),
3128             variadic: false
3129         };
3130         let generics = ast::Generics::default();
3131         assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal,
3132                                  ast::Constness::NotConst,
3133                                  abba_ident, &generics),
3134                    "fn abba()");
3135     }
3136
3137     #[test]
3138     fn test_variant_to_string() {
3139         let ident = token::str_to_ident("principal_skinner");
3140
3141         let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ {
3142             name: ident,
3143             attrs: Vec::new(),
3144             // making this up as I go.... ?
3145             data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
3146             disr_expr: None,
3147         });
3148
3149         let varstr = variant_to_string(&var);
3150         assert_eq!(varstr, "principal_skinner");
3151     }
3152 }