print.rs 81.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub use self::AnnNode::*;

13
use syntax::abi::Abi;
14
use syntax::ast;
15
use syntax::codemap::{self, CodeMap, BytePos, Spanned};
16
use syntax::errors;
17
use syntax::parse::token::{self, keywords, BinOpToken};
18
use syntax::parse::lexer::comments;
19
use syntax::print::pp::{self, break_offset, word, space, hardbreak};
20 21
use syntax::print::pp::{Breaks, eof};
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
22
use syntax::print::pprust::{self as ast_pp, PrintState};
23 24 25
use syntax::ptr::P;

use hir;
26
use hir::{Crate, PatKind, RegionTyParamBound, SelfKind, TraitTyParamBound, TraitBoundModifier};
27 28 29 30 31 32 33 34 35 36 37 38 39

use std::io::{self, Write, Read};

pub enum AnnNode<'a> {
    NodeName(&'a ast::Name),
    NodeBlock(&'a hir::Block),
    NodeItem(&'a hir::Item),
    NodeSubItem(ast::NodeId),
    NodeExpr(&'a hir::Expr),
    NodePat(&'a hir::Pat),
}

pub trait PpAnn {
N
Nick Cameron 已提交
40 41 42 43 44 45
    fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
        Ok(())
    }
    fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
        Ok(())
    }
46 47 48 49 50 51 52 53 54
}

#[derive(Copy, Clone)]
pub struct NoAnn;

impl PpAnn for NoAnn {}


pub struct State<'a> {
55
    krate: Option<&'a Crate>,
56 57
    pub s: pp::Printer<'a>,
    cm: Option<&'a CodeMap>,
58 59 60
    comments: Option<Vec<comments::Comment>>,
    literals: Option<Vec<comments::Literal>>,
    cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral,
61
    boxes: Vec<pp::Breaks>,
N
Nick Cameron 已提交
62
    ann: &'a (PpAnn + 'a),
63 64
}

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
impl<'a> PrintState<'a> for State<'a> {
    fn writer(&mut self) -> &mut pp::Printer<'a> {
        &mut self.s
    }

    fn boxes(&mut self) -> &mut Vec<pp::Breaks> {
        &mut self.boxes
    }

    fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> {
        &mut self.comments
    }

    fn cur_cmnt_and_lit(&mut self) -> &mut ast_pp::CurrentCommentAndLiteral {
        &mut self.cur_cmnt_and_lit
    }

    fn literals(&self) -> &Option<Vec<comments::Literal>> {
        &self.literals
    }
}

87
pub fn rust_printer<'a>(writer: Box<Write + 'a>, krate: Option<&'a Crate>) -> State<'a> {
88
    static NO_ANN: NoAnn = NoAnn;
89
    rust_printer_annotated(writer, &NO_ANN, krate)
90 91
}

N
Niko Matsakis 已提交
92 93 94 95
pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>,
                                  ann: &'a PpAnn,
                                  krate: Option<&'a Crate>)
                                  -> State<'a> {
96
    State {
97
        krate: krate,
98 99 100 101
        s: pp::mk_printer(writer, default_columns),
        cm: None,
        comments: None,
        literals: None,
102
        cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
103
            cur_cmnt: 0,
N
Nick Cameron 已提交
104
            cur_lit: 0,
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
        },
        boxes: Vec::new(),
        ann: ann,
    }
}

#[allow(non_upper_case_globals)]
pub const indent_unit: usize = 4;

#[allow(non_upper_case_globals)]
pub const default_columns: usize = 78;


/// Requires you to pass an input filename and reader so that
/// it can scan the input text for comments and literals to
/// copy forward.
pub fn print_crate<'a>(cm: &'a CodeMap,
122
                       span_diagnostic: &errors::Handler,
123 124 125
                       krate: &hir::Crate,
                       filename: String,
                       input: &mut Read,
N
Nick Cameron 已提交
126
                       out: Box<Write + 'a>,
127
                       ann: &'a PpAnn,
N
Nick Cameron 已提交
128 129
                       is_expanded: bool)
                       -> io::Result<()> {
N
Niko Matsakis 已提交
130 131
    let mut s = State::new_from_input(cm, span_diagnostic, filename, input,
                                      out, ann, is_expanded, Some(krate));
132 133 134 135

    // When printing the AST, we sometimes need to inject `#[no_std]` here.
    // Since you can't compile the HIR, it's not necessary.

J
Jorge Aparicio 已提交
136 137
    s.print_mod(&krate.module, &krate.attrs)?;
    s.print_remaining_comments()?;
138 139 140 141 142
    eof(&mut s.s)
}

impl<'a> State<'a> {
    pub fn new_from_input(cm: &'a CodeMap,
143
                          span_diagnostic: &errors::Handler,
144 145
                          filename: String,
                          input: &mut Read,
N
Nick Cameron 已提交
146
                          out: Box<Write + 'a>,
147
                          ann: &'a PpAnn,
148 149
                          is_expanded: bool,
                          krate: Option<&'a Crate>)
N
Nick Cameron 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
                          -> State<'a> {
        let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic,
                                                                   filename,
                                                                   input);

        State::new(cm,
                   out,
                   ann,
                   Some(cmnts),
                   // If the code is post expansion, don't use the table of
                   // literals, since it doesn't correspond with the literals
                   // in the AST anymore.
                   if is_expanded {
                       None
                   } else {
                       Some(lits)
166 167
                   },
                   krate)
168 169 170
    }

    pub fn new(cm: &'a CodeMap,
N
Nick Cameron 已提交
171
               out: Box<Write + 'a>,
172 173
               ann: &'a PpAnn,
               comments: Option<Vec<comments::Comment>>,
174 175
               literals: Option<Vec<comments::Literal>>,
               krate: Option<&'a Crate>)
N
Nick Cameron 已提交
176
               -> State<'a> {
177
        State {
178
            krate: krate,
179 180
            s: pp::mk_printer(out, default_columns),
            cm: Some(cm),
181 182 183
            comments: comments.clone(),
            literals: literals.clone(),
            cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
184
                cur_cmnt: 0,
N
Nick Cameron 已提交
185
                cur_lit: 0,
186 187 188 189 190 191 192
            },
            boxes: Vec::new(),
            ann: ann,
        }
    }
}

N
Nick Cameron 已提交
193 194
pub fn to_string<F>(f: F) -> String
    where F: FnOnce(&mut State) -> io::Result<()>
195 196 197
{
    let mut wr = Vec::new();
    {
198
        let mut printer = rust_printer(Box::new(&mut wr), None);
199 200 201 202 203 204 205 206
        f(&mut printer).unwrap();
        eof(&mut printer.s).unwrap();
    }
    String::from_utf8(wr).unwrap()
}

pub fn binop_to_string(op: BinOpToken) -> &'static str {
    match op {
N
Nick Cameron 已提交
207 208 209 210 211 212 213 214 215 216
        token::Plus => "+",
        token::Minus => "-",
        token::Star => "*",
        token::Slash => "/",
        token::Percent => "%",
        token::Caret => "^",
        token::And => "&",
        token::Or => "|",
        token::Shl => "<<",
        token::Shr => ">>",
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
    }
}

pub fn ty_to_string(ty: &hir::Ty) -> String {
    to_string(|s| s.print_type(ty))
}

pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String {
    to_string(|s| s.print_bounds("", bounds))
}

pub fn pat_to_string(pat: &hir::Pat) -> String {
    to_string(|s| s.print_pat(pat))
}

pub fn arm_to_string(arm: &hir::Arm) -> String {
    to_string(|s| s.print_arm(arm))
}

pub fn expr_to_string(e: &hir::Expr) -> String {
    to_string(|s| s.print_expr(e))
}

pub fn lifetime_to_string(e: &hir::Lifetime) -> String {
    to_string(|s| s.print_lifetime(e))
}

pub fn stmt_to_string(stmt: &hir::Stmt) -> String {
    to_string(|s| s.print_stmt(stmt))
}

pub fn item_to_string(i: &hir::Item) -> String {
    to_string(|s| s.print_item(i))
}

pub fn impl_item_to_string(i: &hir::ImplItem) -> String {
    to_string(|s| s.print_impl_item(i))
}

pub fn trait_item_to_string(i: &hir::TraitItem) -> String {
    to_string(|s| s.print_trait_item(i))
}

pub fn generics_to_string(generics: &hir::Generics) -> String {
    to_string(|s| s.print_generics(generics))
}

pub fn where_clause_to_string(i: &hir::WhereClause) -> String {
    to_string(|s| s.print_where_clause(i))
}

pub fn fn_block_to_string(p: &hir::FnDecl) -> String {
    to_string(|s| s.print_fn_block_args(p))
}

pub fn path_to_string(p: &hir::Path) -> String {
    to_string(|s| s.print_path(p, false, 0))
}

276 277
pub fn name_to_string(name: ast::Name) -> String {
    to_string(|s| s.print_name(name))
278 279 280 281 282
}

pub fn fun_to_string(decl: &hir::FnDecl,
                     unsafety: hir::Unsafety,
                     constness: hir::Constness,
V
Vadim Petrochenkov 已提交
283
                     name: ast::Name,
284 285 286
                     generics: &hir::Generics)
                     -> String {
    to_string(|s| {
J
Jorge Aparicio 已提交
287 288
        s.head("")?;
        s.print_fn(decl,
J
Jorge Aparicio 已提交
289 290 291 292 293
                   unsafety,
                   constness,
                   Abi::Rust,
                   Some(name),
                   generics,
294
                   &hir::Inherited)?;
J
Jorge Aparicio 已提交
295
        s.end()?; // Close the head box
296 297 298 299 300 301 302
        s.end() // Close the outer box
    })
}

pub fn block_to_string(blk: &hir::Block) -> String {
    to_string(|s| {
        // containing cbox, will be closed by print-block at }
J
Jorge Aparicio 已提交
303
        s.cbox(indent_unit)?;
304
        // head-ibox, will be closed by print-block after {
J
Jorge Aparicio 已提交
305
        s.ibox(0)?;
306 307 308 309 310 311 312 313 314
        s.print_block(blk)
    })
}

pub fn variant_to_string(var: &hir::Variant) -> String {
    to_string(|s| s.print_variant(var))
}

pub fn arg_to_string(arg: &hir::Arg) -> String {
315
    to_string(|s| s.print_arg(arg, false))
316 317
}

318 319
pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String {
    match *vis {
320
        hir::Public => format!("pub {}", s),
321 322
        hir::Visibility::Crate => format!("pub(crate) {}", s),
        hir::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
N
Nick Cameron 已提交
323
        hir::Inherited => s.to_string(),
324 325 326 327 328
    }
}

fn needs_parentheses(expr: &hir::Expr) -> bool {
    match expr.node {
N
Nick Cameron 已提交
329 330
        hir::ExprAssign(..) |
        hir::ExprBinary(..) |
331
        hir::ExprClosure(..) |
N
Nick Cameron 已提交
332
        hir::ExprAssignOp(..) |
333 334
        hir::ExprCast(..) |
        hir::ExprType(..) => true,
335 336 337 338 339 340 341 342 343 344
        _ => false,
    }
}

impl<'a> State<'a> {
    pub fn cbox(&mut self, u: usize) -> io::Result<()> {
        self.boxes.push(pp::Breaks::Consistent);
        pp::cbox(&mut self.s, u)
    }

N
Nick Cameron 已提交
345 346 347
    pub fn nbsp(&mut self) -> io::Result<()> {
        word(&mut self.s, " ")
    }
348 349

    pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
J
Jorge Aparicio 已提交
350
        word(&mut self.s, w)?;
351 352 353 354 355
        self.nbsp()
    }

    pub fn head(&mut self, w: &str) -> io::Result<()> {
        // outer-box is consistent
J
Jorge Aparicio 已提交
356
        self.cbox(indent_unit)?;
357
        // head-box is inconsistent
J
Jorge Aparicio 已提交
358
        self.ibox(w.len() + 1)?;
359 360
        // keyword that starts the head
        if !w.is_empty() {
J
Jorge Aparicio 已提交
361
            self.word_nbsp(w)?;
362 363 364 365 366
        }
        Ok(())
    }

    pub fn bopen(&mut self) -> io::Result<()> {
J
Jorge Aparicio 已提交
367
        word(&mut self.s, "{")?;
368 369 370
        self.end() // close the head-box
    }

N
Nick Cameron 已提交
371
    pub fn bclose_(&mut self, span: codemap::Span, indented: usize) -> io::Result<()> {
372 373
        self.bclose_maybe_open(span, indented, true)
    }
N
Nick Cameron 已提交
374 375 376 377 378
    pub fn bclose_maybe_open(&mut self,
                             span: codemap::Span,
                             indented: usize,
                             close_box: bool)
                             -> io::Result<()> {
J
Jorge Aparicio 已提交
379 380 381
        self.maybe_print_comment(span.hi)?;
        self.break_offset_if_not_bol(1, -(indented as isize))?;
        word(&mut self.s, "}")?;
382
        if close_box {
J
Jorge Aparicio 已提交
383
            self.end()?; // close the outer-box
384 385 386 387 388 389 390 391 392 393
        }
        Ok(())
    }
    pub fn bclose(&mut self, span: codemap::Span) -> io::Result<()> {
        self.bclose_(span, indent_unit)
    }

    pub fn in_cbox(&self) -> bool {
        match self.boxes.last() {
            Some(&last_box) => last_box == pp::Breaks::Consistent,
N
Nick Cameron 已提交
394
            None => false,
395 396 397
        }
    }
    pub fn space_if_not_bol(&mut self) -> io::Result<()> {
N
Nick Cameron 已提交
398
        if !self.is_bol() {
J
Jorge Aparicio 已提交
399
            space(&mut self.s)?;
N
Nick Cameron 已提交
400
        }
401 402
        Ok(())
    }
N
Nick Cameron 已提交
403
    pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> {
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
        if !self.is_bol() {
            break_offset(&mut self.s, n, off)
        } else {
            if off != 0 && self.s.last_token().is_hardbreak_tok() {
                // We do something pretty sketchy here: tuck the nonzero
                // offset-adjustment we were going to deposit along with the
                // break into the previous hardbreak.
                self.s.replace_last_token(pp::hardbreak_tok_offset(off));
            }
            Ok(())
        }
    }

    // Synthesizes a comment that was not textually present in the original source
    // file.
    pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
J
Jorge Aparicio 已提交
420 421 422 423
        word(&mut self.s, "/*")?;
        space(&mut self.s)?;
        word(&mut self.s, &text[..])?;
        space(&mut self.s)?;
424 425 426 427 428 429 430 431
        word(&mut self.s, "*/")
    }


    pub fn commasep_cmnt<T, F, G>(&mut self,
                                  b: Breaks,
                                  elts: &[T],
                                  mut op: F,
N
Nick Cameron 已提交
432 433 434 435
                                  mut get_span: G)
                                  -> io::Result<()>
        where F: FnMut(&mut State, &T) -> io::Result<()>,
              G: FnMut(&T) -> codemap::Span
436
    {
J
Jorge Aparicio 已提交
437
        self.rbox(0, b)?;
438 439 440
        let len = elts.len();
        let mut i = 0;
        for elt in elts {
J
Jorge Aparicio 已提交
441 442
            self.maybe_print_comment(get_span(elt).hi)?;
            op(self, elt)?;
443 444
            i += 1;
            if i < len {
J
Jorge Aparicio 已提交
445 446 447
                word(&mut self.s, ",")?;
                self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi))?;
                self.space_if_not_bol()?;
448 449 450 451 452
            }
        }
        self.end()
    }

N
Nick Cameron 已提交
453
    pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<hir::Expr>]) -> io::Result<()> {
454
        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
455 456
    }

N
Nick Cameron 已提交
457
    pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
J
Jorge Aparicio 已提交
458
        self.print_inner_attributes(attrs)?;
459
        for item_id in &_mod.item_ids {
J
Jorge Aparicio 已提交
460
            self.print_item_id(item_id)?;
461 462 463 464
        }
        Ok(())
    }

N
Nick Cameron 已提交
465 466 467 468
    pub fn print_foreign_mod(&mut self,
                             nmod: &hir::ForeignMod,
                             attrs: &[ast::Attribute])
                             -> io::Result<()> {
J
Jorge Aparicio 已提交
469
        self.print_inner_attributes(attrs)?;
470
        for item in &nmod.items {
J
Jorge Aparicio 已提交
471
            self.print_foreign_item(item)?;
472 473 474 475
        }
        Ok(())
    }

N
Nick Cameron 已提交
476
    pub fn print_opt_lifetime(&mut self, lifetime: &Option<hir::Lifetime>) -> io::Result<()> {
477
        if let Some(l) = *lifetime {
J
Jorge Aparicio 已提交
478 479
            self.print_lifetime(&l)?;
            self.nbsp()?;
480 481 482 483 484
        }
        Ok(())
    }

    pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
J
Jorge Aparicio 已提交
485 486
        self.maybe_print_comment(ty.span.lo)?;
        self.ibox(0)?;
487 488
        match ty.node {
            hir::TyVec(ref ty) => {
J
Jorge Aparicio 已提交
489 490 491
                word(&mut self.s, "[")?;
                self.print_type(&ty)?;
                word(&mut self.s, "]")?;
492 493
            }
            hir::TyPtr(ref mt) => {
J
Jorge Aparicio 已提交
494
                word(&mut self.s, "*")?;
495
                match mt.mutbl {
J
Jorge Aparicio 已提交
496 497
                    hir::MutMutable => self.word_nbsp("mut")?,
                    hir::MutImmutable => self.word_nbsp("const")?,
498
                }
J
Jorge Aparicio 已提交
499
                self.print_type(&mt.ty)?;
500 501
            }
            hir::TyRptr(ref lifetime, ref mt) => {
J
Jorge Aparicio 已提交
502 503 504
                word(&mut self.s, "&")?;
                self.print_opt_lifetime(lifetime)?;
                self.print_mt(mt)?;
505 506
            }
            hir::TyTup(ref elts) => {
J
Jorge Aparicio 已提交
507 508
                self.popen()?;
                self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty))?;
509
                if elts.len() == 1 {
J
Jorge Aparicio 已提交
510
                    word(&mut self.s, ",")?;
511
                }
J
Jorge Aparicio 已提交
512
                self.pclose()?;
513 514 515 516
            }
            hir::TyBareFn(ref f) => {
                let generics = hir::Generics {
                    lifetimes: f.lifetimes.clone(),
517
                    ty_params: hir::HirVec::new(),
518 519
                    where_clause: hir::WhereClause {
                        id: ast::DUMMY_NODE_ID,
520
                        predicates: hir::HirVec::new(),
521 522
                    },
                };
523
                self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics)?;
524 525
            }
            hir::TyPath(None, ref path) => {
J
Jorge Aparicio 已提交
526
                self.print_path(path, false, 0)?;
527 528
            }
            hir::TyPath(Some(ref qself), ref path) => {
J
Jorge Aparicio 已提交
529
                self.print_qpath(path, qself, false)?
530 531
            }
            hir::TyObjectSum(ref ty, ref bounds) => {
J
Jorge Aparicio 已提交
532 533
                self.print_type(&ty)?;
                self.print_bounds("+", &bounds[..])?;
534 535
            }
            hir::TyPolyTraitRef(ref bounds) => {
J
Jorge Aparicio 已提交
536
                self.print_bounds("", &bounds[..])?;
537 538
            }
            hir::TyFixedLengthVec(ref ty, ref v) => {
J
Jorge Aparicio 已提交
539 540 541 542 543
                word(&mut self.s, "[")?;
                self.print_type(&ty)?;
                word(&mut self.s, "; ")?;
                self.print_expr(&v)?;
                word(&mut self.s, "]")?;
544 545
            }
            hir::TyTypeof(ref e) => {
J
Jorge Aparicio 已提交
546 547 548
                word(&mut self.s, "typeof(")?;
                self.print_expr(&e)?;
                word(&mut self.s, ")")?;
549 550
            }
            hir::TyInfer => {
J
Jorge Aparicio 已提交
551
                word(&mut self.s, "_")?;
552 553 554 555 556
            }
        }
        self.end()
    }

N
Nick Cameron 已提交
557
    pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()> {
J
Jorge Aparicio 已提交
558 559 560
        self.hardbreak_if_not_bol()?;
        self.maybe_print_comment(item.span.lo)?;
        self.print_outer_attributes(&item.attrs)?;
561 562
        match item.node {
            hir::ForeignItemFn(ref decl, ref generics) => {
J
Jorge Aparicio 已提交
563 564
                self.head("")?;
                self.print_fn(decl,
J
Jorge Aparicio 已提交
565 566 567 568 569
                              hir::Unsafety::Normal,
                              hir::Constness::NotConst,
                              Abi::Rust,
                              Some(item.name),
                              generics,
570
                              &item.vis)?;
J
Jorge Aparicio 已提交
571 572
                self.end()?; // end head-ibox
                word(&mut self.s, ";")?;
573 574 575
                self.end() // end the outer fn box
            }
            hir::ForeignItemStatic(ref t, m) => {
576
                self.head(&visibility_qualified(&item.vis, "static"))?;
577
                if m {
J
Jorge Aparicio 已提交
578
                    self.word_space("mut")?;
579
                }
J
Jorge Aparicio 已提交
580 581 582 583 584
                self.print_name(item.name)?;
                self.word_space(":")?;
                self.print_type(&t)?;
                word(&mut self.s, ";")?;
                self.end()?; // end the head-ibox
585 586 587 588 589 590
                self.end() // end the outer cbox
            }
        }
    }

    fn print_associated_const(&mut self,
V
Vadim Petrochenkov 已提交
591
                              name: ast::Name,
592 593
                              ty: &hir::Ty,
                              default: Option<&hir::Expr>,
594
                              vis: &hir::Visibility)
N
Nick Cameron 已提交
595
                              -> io::Result<()> {
J
Jorge Aparicio 已提交
596 597 598 599 600
        word(&mut self.s, &visibility_qualified(vis, ""))?;
        self.word_space("const")?;
        self.print_name(name)?;
        self.word_space(":")?;
        self.print_type(ty)?;
601
        if let Some(expr) = default {
J
Jorge Aparicio 已提交
602 603 604
            space(&mut self.s)?;
            self.word_space("=")?;
            self.print_expr(expr)?;
605 606 607 608 609
        }
        word(&mut self.s, ";")
    }

    fn print_associated_type(&mut self,
V
Vadim Petrochenkov 已提交
610
                             name: ast::Name,
611 612 613
                             bounds: Option<&hir::TyParamBounds>,
                             ty: Option<&hir::Ty>)
                             -> io::Result<()> {
J
Jorge Aparicio 已提交
614 615
        self.word_space("type")?;
        self.print_name(name)?;
616
        if let Some(bounds) = bounds {
J
Jorge Aparicio 已提交
617
            self.print_bounds(":", bounds)?;
618 619
        }
        if let Some(ty) = ty {
J
Jorge Aparicio 已提交
620 621 622
            space(&mut self.s)?;
            self.word_space("=")?;
            self.print_type(ty)?;
623 624 625 626
        }
        word(&mut self.s, ";")
    }

627 628 629 630 631 632 633 634 635 636
    pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> {
        if let Some(krate) = self.krate {
            // skip nested items if krate context was not provided
            let item = &krate.items[&item_id.id];
            self.print_item(item)
        } else {
            Ok(())
        }
    }

637 638
    /// Pretty-print an item
    pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
J
Jorge Aparicio 已提交
639 640 641 642
        self.hardbreak_if_not_bol()?;
        self.maybe_print_comment(item.span.lo)?;
        self.print_outer_attributes(&item.attrs)?;
        self.ann.pre(self, NodeItem(item))?;
643 644
        match item.node {
            hir::ItemExternCrate(ref optional_path) => {
645
                self.head(&visibility_qualified(&item.vis, "extern crate"))?;
646 647 648
                if let Some(p) = *optional_path {
                    let val = p.as_str();
                    if val.contains("-") {
J
Jorge Aparicio 已提交
649
                        self.print_string(&val, ast::StrStyle::Cooked)?;
650
                    } else {
J
Jorge Aparicio 已提交
651
                        self.print_name(p)?;
652
                    }
J
Jorge Aparicio 已提交
653 654 655
                    space(&mut self.s)?;
                    word(&mut self.s, "as")?;
                    space(&mut self.s)?;
656
                }
J
Jorge Aparicio 已提交
657 658 659 660
                self.print_name(item.name)?;
                word(&mut self.s, ";")?;
                self.end()?; // end inner head-block
                self.end()?; // end outer head-block
661 662
            }
            hir::ItemUse(ref vp) => {
663
                self.head(&visibility_qualified(&item.vis, "use"))?;
J
Jorge Aparicio 已提交
664 665 666 667
                self.print_view_path(&vp)?;
                word(&mut self.s, ";")?;
                self.end()?; // end inner head-block
                self.end()?; // end outer head-block
668 669
            }
            hir::ItemStatic(ref ty, m, ref expr) => {
670
                self.head(&visibility_qualified(&item.vis, "static"))?;
671
                if m == hir::MutMutable {
J
Jorge Aparicio 已提交
672
                    self.word_space("mut")?;
673
                }
J
Jorge Aparicio 已提交
674 675 676 677 678
                self.print_name(item.name)?;
                self.word_space(":")?;
                self.print_type(&ty)?;
                space(&mut self.s)?;
                self.end()?; // end the head-ibox
679

J
Jorge Aparicio 已提交
680 681 682 683
                self.word_space("=")?;
                self.print_expr(&expr)?;
                word(&mut self.s, ";")?;
                self.end()?; // end the outer cbox
684 685
            }
            hir::ItemConst(ref ty, ref expr) => {
686
                self.head(&visibility_qualified(&item.vis, "const"))?;
J
Jorge Aparicio 已提交
687 688 689 690 691 692 693 694 695 696
                self.print_name(item.name)?;
                self.word_space(":")?;
                self.print_type(&ty)?;
                space(&mut self.s)?;
                self.end()?; // end the head-ibox

                self.word_space("=")?;
                self.print_expr(&expr)?;
                word(&mut self.s, ";")?;
                self.end()?; // end the outer cbox
697 698
            }
            hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
J
Jorge Aparicio 已提交
699 700
                self.head("")?;
                self.print_fn(decl,
J
Jorge Aparicio 已提交
701 702 703 704 705
                              unsafety,
                              constness,
                              abi,
                              Some(item.name),
                              typarams,
706
                              &item.vis)?;
J
Jorge Aparicio 已提交
707 708
                word(&mut self.s, " ")?;
                self.print_block_with_attrs(&body, &item.attrs)?;
709 710
            }
            hir::ItemMod(ref _mod) => {
711
                self.head(&visibility_qualified(&item.vis, "mod"))?;
J
Jorge Aparicio 已提交
712 713 714 715 716
                self.print_name(item.name)?;
                self.nbsp()?;
                self.bopen()?;
                self.print_mod(_mod, &item.attrs)?;
                self.bclose(item.span)?;
717 718
            }
            hir::ItemForeignMod(ref nmod) => {
J
Jorge Aparicio 已提交
719 720 721 722 723
                self.head("extern")?;
                self.word_nbsp(&nmod.abi.to_string())?;
                self.bopen()?;
                self.print_foreign_mod(nmod, &item.attrs)?;
                self.bclose(item.span)?;
724 725
            }
            hir::ItemTy(ref ty, ref params) => {
J
Jorge Aparicio 已提交
726 727
                self.ibox(indent_unit)?;
                self.ibox(0)?;
728
                self.word_nbsp(&visibility_qualified(&item.vis, "type"))?;
J
Jorge Aparicio 已提交
729 730 731 732 733 734 735 736 737 738
                self.print_name(item.name)?;
                self.print_generics(params)?;
                self.end()?; // end the inner ibox

                self.print_where_clause(&params.where_clause)?;
                space(&mut self.s)?;
                self.word_space("=")?;
                self.print_type(&ty)?;
                word(&mut self.s, ";")?;
                self.end()?; // end the outer ibox
739 740
            }
            hir::ItemEnum(ref enum_definition, ref params) => {
741
                self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?;
742 743
            }
            hir::ItemStruct(ref struct_def, ref generics) => {
744
                self.head(&visibility_qualified(&item.vis, "struct"))?;
J
Jorge Aparicio 已提交
745
                self.print_struct(struct_def, generics, item.name, item.span, true)?;
746 747 748
            }

            hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
J
Jorge Aparicio 已提交
749
                self.head("")?;
750
                self.print_visibility(&item.vis)?;
J
Jorge Aparicio 已提交
751 752 753 754 755 756 757 758
                self.print_unsafety(unsafety)?;
                self.word_nbsp("impl")?;
                self.print_trait_ref(trait_ref)?;
                space(&mut self.s)?;
                self.word_space("for")?;
                self.word_space("..")?;
                self.bopen()?;
                self.bclose(item.span)?;
759 760 761 762 763 764 765
            }
            hir::ItemImpl(unsafety,
                          polarity,
                          ref generics,
                          ref opt_trait,
                          ref ty,
                          ref impl_items) => {
J
Jorge Aparicio 已提交
766
                self.head("")?;
767
                self.print_visibility(&item.vis)?;
J
Jorge Aparicio 已提交
768 769
                self.print_unsafety(unsafety)?;
                self.word_nbsp("impl")?;
770 771

                if generics.is_parameterized() {
J
Jorge Aparicio 已提交
772 773
                    self.print_generics(generics)?;
                    space(&mut self.s)?;
774 775 776 777
                }

                match polarity {
                    hir::ImplPolarity::Negative => {
J
Jorge Aparicio 已提交
778
                        word(&mut self.s, "!")?;
N
Nick Cameron 已提交
779
                    }
780 781 782 783 784
                    _ => {}
                }

                match opt_trait {
                    &Some(ref t) => {
J
Jorge Aparicio 已提交
785 786 787
                        self.print_trait_ref(t)?;
                        space(&mut self.s)?;
                        self.word_space("for")?;
788 789 790 791
                    }
                    &None => {}
                }

J
Jorge Aparicio 已提交
792 793
                self.print_type(&ty)?;
                self.print_where_clause(&generics.where_clause)?;
794

J
Jorge Aparicio 已提交
795 796 797
                space(&mut self.s)?;
                self.bopen()?;
                self.print_inner_attributes(&item.attrs)?;
798
                for impl_item in impl_items {
J
Jorge Aparicio 已提交
799
                    self.print_impl_item(impl_item)?;
800
                }
J
Jorge Aparicio 已提交
801
                self.bclose(item.span)?;
802 803
            }
            hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
J
Jorge Aparicio 已提交
804
                self.head("")?;
805
                self.print_visibility(&item.vis)?;
J
Jorge Aparicio 已提交
806 807 808 809
                self.print_unsafety(unsafety)?;
                self.word_nbsp("trait")?;
                self.print_name(item.name)?;
                self.print_generics(generics)?;
810 811 812
                let mut real_bounds = Vec::with_capacity(bounds.len());
                for b in bounds.iter() {
                    if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
J
Jorge Aparicio 已提交
813 814 815
                        space(&mut self.s)?;
                        self.word_space("for ?")?;
                        self.print_trait_ref(&ptr.trait_ref)?;
816 817 818 819
                    } else {
                        real_bounds.push(b.clone());
                    }
                }
J
Jorge Aparicio 已提交
820 821 822 823
                self.print_bounds(":", &real_bounds[..])?;
                self.print_where_clause(&generics.where_clause)?;
                word(&mut self.s, " ")?;
                self.bopen()?;
824
                for trait_item in trait_items {
J
Jorge Aparicio 已提交
825
                    self.print_trait_item(trait_item)?;
826
                }
J
Jorge Aparicio 已提交
827
                self.bclose(item.span)?;
828 829 830 831 832 833 834 835 836 837 838
            }
        }
        self.ann.post(self, NodeItem(item))
    }

    fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
        self.print_path(&t.path, false, 0)
    }

    fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> {
        if !lifetimes.is_empty() {
J
Jorge Aparicio 已提交
839
            word(&mut self.s, "for<")?;
840 841 842
            let mut comma = false;
            for lifetime_def in lifetimes {
                if comma {
J
Jorge Aparicio 已提交
843
                    self.word_space(",")?
844
                }
J
Jorge Aparicio 已提交
845
                self.print_lifetime_def(lifetime_def)?;
846 847
                comma = true;
            }
J
Jorge Aparicio 已提交
848
            word(&mut self.s, ">")?;
849 850 851 852 853
        }
        Ok(())
    }

    fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> {
J
Jorge Aparicio 已提交
854
        self.print_formal_lifetime_list(&t.bound_lifetimes)?;
855 856 857
        self.print_trait_ref(&t.trait_ref)
    }

N
Nick Cameron 已提交
858 859 860 861
    pub fn print_enum_def(&mut self,
                          enum_definition: &hir::EnumDef,
                          generics: &hir::Generics,
                          name: ast::Name,
862
                          span: codemap::Span,
863
                          visibility: &hir::Visibility)
N
Nick Cameron 已提交
864
                          -> io::Result<()> {
J
Jorge Aparicio 已提交
865 866 867 868 869
        self.head(&visibility_qualified(visibility, "enum"))?;
        self.print_name(name)?;
        self.print_generics(generics)?;
        self.print_where_clause(&generics.where_clause)?;
        space(&mut self.s)?;
870 871 872 873
        self.print_variants(&enum_definition.variants, span)
    }

    pub fn print_variants(&mut self,
874
                          variants: &[hir::Variant],
N
Nick Cameron 已提交
875 876
                          span: codemap::Span)
                          -> io::Result<()> {
J
Jorge Aparicio 已提交
877
        self.bopen()?;
878
        for v in variants {
J
Jorge Aparicio 已提交
879 880 881 882 883 884 885 886
            self.space_if_not_bol()?;
            self.maybe_print_comment(v.span.lo)?;
            self.print_outer_attributes(&v.node.attrs)?;
            self.ibox(indent_unit)?;
            self.print_variant(v)?;
            word(&mut self.s, ",")?;
            self.end()?;
            self.maybe_print_trailing_comment(v.span, None)?;
887 888 889 890
        }
        self.bclose(span)
    }

891 892
    pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
        match *vis {
893
            hir::Public => self.word_nbsp("pub"),
894 895 896
            hir::Visibility::Crate => self.word_nbsp("pub(crate)"),
            hir::Visibility::Restricted { ref path, .. } =>
                self.word_nbsp(&format!("pub({})", path)),
N
Nick Cameron 已提交
897
            hir::Inherited => Ok(()),
898 899 900 901
        }
    }

    pub fn print_struct(&mut self,
902
                        struct_def: &hir::VariantData,
903
                        generics: &hir::Generics,
V
Vadim Petrochenkov 已提交
904
                        name: ast::Name,
905 906
                        span: codemap::Span,
                        print_finalizer: bool)
N
Nick Cameron 已提交
907
                        -> io::Result<()> {
J
Jorge Aparicio 已提交
908 909
        self.print_name(name)?;
        self.print_generics(generics)?;
910 911
        if !struct_def.is_struct() {
            if struct_def.is_tuple() {
J
Jorge Aparicio 已提交
912 913
                self.popen()?;
                self.commasep(Inconsistent, struct_def.fields(), |s, field| {
914
                    s.print_visibility(&field.vis)?;
J
Jorge Aparicio 已提交
915
                    s.maybe_print_comment(field.span.lo)?;
916
                    s.print_type(&field.ty)
J
Jorge Aparicio 已提交
917 918
                })?;
                self.pclose()?;
919
            }
J
Jorge Aparicio 已提交
920
            self.print_where_clause(&generics.where_clause)?;
921
            if print_finalizer {
J
Jorge Aparicio 已提交
922
                word(&mut self.s, ";")?;
923
            }
J
Jorge Aparicio 已提交
924
            self.end()?;
925 926
            self.end() // close the outer-box
        } else {
J
Jorge Aparicio 已提交
927 928 929 930
            self.print_where_clause(&generics.where_clause)?;
            self.nbsp()?;
            self.bopen()?;
            self.hardbreak_if_not_bol()?;
931

932
            for field in struct_def.fields() {
J
Jorge Aparicio 已提交
933 934 935
                self.hardbreak_if_not_bol()?;
                self.maybe_print_comment(field.span.lo)?;
                self.print_outer_attributes(&field.attrs)?;
936
                self.print_visibility(&field.vis)?;
J
Jorge Aparicio 已提交
937 938 939 940
                self.print_name(field.name)?;
                self.word_nbsp(":")?;
                self.print_type(&field.ty)?;
                word(&mut self.s, ",")?;
941 942 943 944 945 946 947
            }

            self.bclose(span)
        }
    }

    pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
J
Jorge Aparicio 已提交
948
        self.head("")?;
949
        let generics = hir::Generics::empty();
J
Jorge Aparicio 已提交
950
        self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
951 952
        match v.node.disr_expr {
            Some(ref d) => {
J
Jorge Aparicio 已提交
953 954
                space(&mut self.s)?;
                self.word_space("=")?;
955
                self.print_expr(&d)
956
            }
N
Nick Cameron 已提交
957
            _ => Ok(()),
958 959 960
        }
    }
    pub fn print_method_sig(&mut self,
V
Vadim Petrochenkov 已提交
961
                            name: ast::Name,
962
                            m: &hir::MethodSig,
963
                            vis: &hir::Visibility)
964 965 966 967 968
                            -> io::Result<()> {
        self.print_fn(&m.decl,
                      m.unsafety,
                      m.constness,
                      m.abi,
V
Vadim Petrochenkov 已提交
969
                      Some(name),
970 971 972 973
                      &m.generics,
                      vis)
    }

N
Nick Cameron 已提交
974
    pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
J
Jorge Aparicio 已提交
975 976 977 978
        self.ann.pre(self, NodeSubItem(ti.id))?;
        self.hardbreak_if_not_bol()?;
        self.maybe_print_comment(ti.span.lo)?;
        self.print_outer_attributes(&ti.attrs)?;
979 980
        match ti.node {
            hir::ConstTraitItem(ref ty, ref default) => {
J
Jorge Aparicio 已提交
981
                self.print_associated_const(ti.name,
J
Jorge Aparicio 已提交
982 983
                                            &ty,
                                            default.as_ref().map(|expr| &**expr),
984
                                            &hir::Inherited)?;
985 986 987
            }
            hir::MethodTraitItem(ref sig, ref body) => {
                if body.is_some() {
J
Jorge Aparicio 已提交
988
                    self.head("")?;
989
                }
990
                self.print_method_sig(ti.name, sig, &hir::Inherited)?;
991
                if let Some(ref body) = *body {
J
Jorge Aparicio 已提交
992 993
                    self.nbsp()?;
                    self.print_block_with_attrs(body, &ti.attrs)?;
994
                } else {
J
Jorge Aparicio 已提交
995
                    word(&mut self.s, ";")?;
996 997 998
                }
            }
            hir::TypeTraitItem(ref bounds, ref default) => {
J
Jorge Aparicio 已提交
999
                self.print_associated_type(ti.name,
J
Jorge Aparicio 已提交
1000 1001
                                           Some(bounds),
                                           default.as_ref().map(|ty| &**ty))?;
1002 1003 1004 1005 1006 1007
            }
        }
        self.ann.post(self, NodeSubItem(ti.id))
    }

    pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
J
Jorge Aparicio 已提交
1008 1009 1010 1011
        self.ann.pre(self, NodeSubItem(ii.id))?;
        self.hardbreak_if_not_bol()?;
        self.maybe_print_comment(ii.span.lo)?;
        self.print_outer_attributes(&ii.attrs)?;
1012 1013

        if let hir::Defaultness::Default = ii.defaultness {
J
Jorge Aparicio 已提交
1014
            self.word_nbsp("default")?;
1015 1016
        }

1017
        match ii.node {
1018
            hir::ImplItemKind::Const(ref ty, ref expr) => {
1019
                self.print_associated_const(ii.name, &ty, Some(&expr), &ii.vis)?;
1020
            }
1021
            hir::ImplItemKind::Method(ref sig, ref body) => {
J
Jorge Aparicio 已提交
1022
                self.head("")?;
1023
                self.print_method_sig(ii.name, sig, &ii.vis)?;
J
Jorge Aparicio 已提交
1024 1025
                self.nbsp()?;
                self.print_block_with_attrs(body, &ii.attrs)?;
1026
            }
1027
            hir::ImplItemKind::Type(ref ty) => {
J
Jorge Aparicio 已提交
1028
                self.print_associated_type(ii.name, None, Some(ty))?;
1029 1030 1031 1032 1033 1034
            }
        }
        self.ann.post(self, NodeSubItem(ii.id))
    }

    pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
J
Jorge Aparicio 已提交
1035
        self.maybe_print_comment(st.span.lo)?;
1036 1037
        match st.node {
            hir::StmtDecl(ref decl, _) => {
J
Jorge Aparicio 已提交
1038
                self.print_decl(&decl)?;
1039 1040
            }
            hir::StmtExpr(ref expr, _) => {
J
Jorge Aparicio 已提交
1041 1042
                self.space_if_not_bol()?;
                self.print_expr(&expr)?;
1043 1044
            }
            hir::StmtSemi(ref expr, _) => {
J
Jorge Aparicio 已提交
1045 1046 1047
                self.space_if_not_bol()?;
                self.print_expr(&expr)?;
                word(&mut self.s, ";")?;
1048 1049 1050
            }
        }
        if stmt_ends_with_semi(&st.node) {
J
Jorge Aparicio 已提交
1051
            word(&mut self.s, ";")?;
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
        }
        self.maybe_print_trailing_comment(st.span, None)
    }

    pub fn print_block(&mut self, blk: &hir::Block) -> io::Result<()> {
        self.print_block_with_attrs(blk, &[])
    }

    pub fn print_block_unclosed(&mut self, blk: &hir::Block) -> io::Result<()> {
        self.print_block_unclosed_indent(blk, indent_unit)
    }

N
Nick Cameron 已提交
1064 1065 1066 1067
    pub fn print_block_unclosed_indent(&mut self,
                                       blk: &hir::Block,
                                       indented: usize)
                                       -> io::Result<()> {
1068 1069 1070 1071 1072
        self.print_block_maybe_unclosed(blk, indented, &[], false)
    }

    pub fn print_block_with_attrs(&mut self,
                                  blk: &hir::Block,
N
Nick Cameron 已提交
1073 1074
                                  attrs: &[ast::Attribute])
                                  -> io::Result<()> {
1075 1076 1077 1078 1079 1080
        self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
    }

    pub fn print_block_maybe_unclosed(&mut self,
                                      blk: &hir::Block,
                                      indented: usize,
1081
                                      attrs: &[ast::Attribute],
N
Nick Cameron 已提交
1082 1083
                                      close_box: bool)
                                      -> io::Result<()> {
1084
        match blk.rules {
J
Jorge Aparicio 已提交
1085 1086 1087 1088 1089
            hir::UnsafeBlock(..) => self.word_space("unsafe")?,
            hir::PushUnsafeBlock(..) => self.word_space("push_unsafe")?,
            hir::PopUnsafeBlock(..) => self.word_space("pop_unsafe")?,
            hir::PushUnstableBlock => self.word_space("push_unstable")?,
            hir::PopUnstableBlock => self.word_space("pop_unstable")?,
N
Nick Cameron 已提交
1090
            hir::DefaultBlock => (),
1091
        }
J
Jorge Aparicio 已提交
1092 1093 1094
        self.maybe_print_comment(blk.span.lo)?;
        self.ann.pre(self, NodeBlock(blk))?;
        self.bopen()?;
1095

J
Jorge Aparicio 已提交
1096
        self.print_inner_attributes(attrs)?;
1097 1098

        for st in &blk.stmts {
J
Jorge Aparicio 已提交
1099
            self.print_stmt(st)?;
1100 1101 1102
        }
        match blk.expr {
            Some(ref expr) => {
J
Jorge Aparicio 已提交
1103 1104 1105
                self.space_if_not_bol()?;
                self.print_expr(&expr)?;
                self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))?;
1106
            }
N
Nick Cameron 已提交
1107
            _ => (),
1108
        }
J
Jorge Aparicio 已提交
1109
        self.bclose_maybe_open(blk.span, indented, close_box)?;
1110 1111 1112 1113 1114 1115 1116 1117 1118
        self.ann.post(self, NodeBlock(blk))
    }

    fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> {
        match els {
            Some(_else) => {
                match _else.node {
                    // "another else-if"
                    hir::ExprIf(ref i, ref then, ref e) => {
J
Jorge Aparicio 已提交
1119 1120 1121 1122 1123 1124
                        self.cbox(indent_unit - 1)?;
                        self.ibox(0)?;
                        word(&mut self.s, " else if ")?;
                        self.print_expr(&i)?;
                        space(&mut self.s)?;
                        self.print_block(&then)?;
1125 1126 1127 1128
                        self.print_else(e.as_ref().map(|e| &**e))
                    }
                    // "final else"
                    hir::ExprBlock(ref b) => {
J
Jorge Aparicio 已提交
1129 1130 1131
                        self.cbox(indent_unit - 1)?;
                        self.ibox(0)?;
                        word(&mut self.s, " else ")?;
1132
                        self.print_block(&b)
1133 1134 1135 1136 1137 1138 1139
                    }
                    // BLEAH, constraints would be great here
                    _ => {
                        panic!("print_if saw if with weird alternative");
                    }
                }
            }
N
Nick Cameron 已提交
1140
            _ => Ok(()),
1141 1142 1143
        }
    }

N
Nick Cameron 已提交
1144 1145 1146 1147 1148
    pub fn print_if(&mut self,
                    test: &hir::Expr,
                    blk: &hir::Block,
                    elseopt: Option<&hir::Expr>)
                    -> io::Result<()> {
J
Jorge Aparicio 已提交
1149 1150 1151 1152
        self.head("if")?;
        self.print_expr(test)?;
        space(&mut self.s)?;
        self.print_block(blk)?;
1153 1154 1155
        self.print_else(elseopt)
    }

N
Nick Cameron 已提交
1156 1157 1158 1159 1160 1161
    pub fn print_if_let(&mut self,
                        pat: &hir::Pat,
                        expr: &hir::Expr,
                        blk: &hir::Block,
                        elseopt: Option<&hir::Expr>)
                        -> io::Result<()> {
J
Jorge Aparicio 已提交
1162 1163 1164 1165 1166 1167 1168
        self.head("if let")?;
        self.print_pat(pat)?;
        space(&mut self.s)?;
        self.word_space("=")?;
        self.print_expr(expr)?;
        space(&mut self.s)?;
        self.print_block(blk)?;
1169 1170 1171 1172 1173
        self.print_else(elseopt)
    }


    fn print_call_post(&mut self, args: &[P<hir::Expr>]) -> io::Result<()> {
J
Jorge Aparicio 已提交
1174 1175
        self.popen()?;
        self.commasep_exprs(Inconsistent, args)?;
1176 1177 1178 1179 1180 1181
        self.pclose()
    }

    pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr) -> io::Result<()> {
        let needs_par = needs_parentheses(expr);
        if needs_par {
J
Jorge Aparicio 已提交
1182
            self.popen()?;
1183
        }
J
Jorge Aparicio 已提交
1184
        self.print_expr(expr)?;
1185
        if needs_par {
J
Jorge Aparicio 已提交
1186
            self.pclose()?;
1187 1188 1189 1190 1191
        }
        Ok(())
    }

    fn print_expr_vec(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> {
J
Jorge Aparicio 已提交
1192 1193 1194 1195
        self.ibox(indent_unit)?;
        word(&mut self.s, "[")?;
        self.commasep_exprs(Inconsistent, &exprs[..])?;
        word(&mut self.s, "]")?;
1196 1197 1198
        self.end()
    }

N
Nick Cameron 已提交
1199
    fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> {
J
Jorge Aparicio 已提交
1200 1201 1202 1203 1204 1205
        self.ibox(indent_unit)?;
        word(&mut self.s, "[")?;
        self.print_expr(element)?;
        self.word_space(";")?;
        self.print_expr(count)?;
        word(&mut self.s, "]")?;
1206 1207 1208 1209 1210 1211
        self.end()
    }

    fn print_expr_struct(&mut self,
                         path: &hir::Path,
                         fields: &[hir::Field],
N
Nick Cameron 已提交
1212 1213
                         wth: &Option<P<hir::Expr>>)
                         -> io::Result<()> {
J
Jorge Aparicio 已提交
1214 1215 1216
        self.print_path(path, true, 0)?;
        word(&mut self.s, "{")?;
        self.commasep_cmnt(Consistent,
J
Jorge Aparicio 已提交
1217 1218 1219 1220 1221 1222 1223 1224 1225
                           &fields[..],
                           |s, field| {
                               s.ibox(indent_unit)?;
                               s.print_name(field.name.node)?;
                               s.word_space(":")?;
                               s.print_expr(&field.expr)?;
                               s.end()
                           },
                           |f| f.span)?;
1226 1227
        match *wth {
            Some(ref expr) => {
J
Jorge Aparicio 已提交
1228
                self.ibox(indent_unit)?;
1229
                if !fields.is_empty() {
J
Jorge Aparicio 已提交
1230 1231
                    word(&mut self.s, ",")?;
                    space(&mut self.s)?;
1232
                }
J
Jorge Aparicio 已提交
1233 1234 1235
                word(&mut self.s, "..")?;
                self.print_expr(&expr)?;
                self.end()?;
1236 1237
            }
            _ => if !fields.is_empty() {
J
Jorge Aparicio 已提交
1238
                word(&mut self.s, ",")?
N
Nick Cameron 已提交
1239
            },
1240
        }
J
Jorge Aparicio 已提交
1241
        word(&mut self.s, "}")?;
1242 1243 1244 1245
        Ok(())
    }

    fn print_expr_tup(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> {
J
Jorge Aparicio 已提交
1246 1247
        self.popen()?;
        self.commasep_exprs(Inconsistent, &exprs[..])?;
1248
        if exprs.len() == 1 {
J
Jorge Aparicio 已提交
1249
            word(&mut self.s, ",")?;
1250 1251 1252 1253
        }
        self.pclose()
    }

N
Nick Cameron 已提交
1254
    fn print_expr_call(&mut self, func: &hir::Expr, args: &[P<hir::Expr>]) -> io::Result<()> {
J
Jorge Aparicio 已提交
1255
        self.print_expr_maybe_paren(func)?;
1256 1257 1258 1259
        self.print_call_post(args)
    }

    fn print_expr_method_call(&mut self,
1260
                              name: Spanned<ast::Name>,
1261
                              tys: &[P<hir::Ty>],
N
Nick Cameron 已提交
1262 1263
                              args: &[P<hir::Expr>])
                              -> io::Result<()> {
1264
        let base_args = &args[1..];
J
Jorge Aparicio 已提交
1265 1266 1267
        self.print_expr(&args[0])?;
        word(&mut self.s, ".")?;
        self.print_name(name.node)?;
1268
        if !tys.is_empty() {
J
Jorge Aparicio 已提交
1269 1270 1271
            word(&mut self.s, "::<")?;
            self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))?;
            word(&mut self.s, ">")?;
1272 1273 1274 1275 1276 1277 1278
        }
        self.print_call_post(base_args)
    }

    fn print_expr_binary(&mut self,
                         op: hir::BinOp,
                         lhs: &hir::Expr,
N
Nick Cameron 已提交
1279 1280
                         rhs: &hir::Expr)
                         -> io::Result<()> {
J
Jorge Aparicio 已提交
1281 1282
        self.print_expr(lhs)?;
        space(&mut self.s)?;
1283
        self.word_space(op.node.as_str())?;
1284 1285 1286
        self.print_expr(rhs)
    }

N
Nick Cameron 已提交
1287
    fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> {
1288
        word(&mut self.s, op.as_str())?;
1289 1290 1291 1292 1293
        self.print_expr_maybe_paren(expr)
    }

    fn print_expr_addr_of(&mut self,
                          mutability: hir::Mutability,
N
Nick Cameron 已提交
1294 1295
                          expr: &hir::Expr)
                          -> io::Result<()> {
J
Jorge Aparicio 已提交
1296 1297
        word(&mut self.s, "&")?;
        self.print_mutability(mutability)?;
1298 1299 1300 1301
        self.print_expr_maybe_paren(expr)
    }

    pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
J
Jorge Aparicio 已提交
1302 1303 1304
        self.maybe_print_comment(expr.span.lo)?;
        self.ibox(indent_unit)?;
        self.ann.pre(self, NodeExpr(expr))?;
1305
        match expr.node {
1306
            hir::ExprBox(ref expr) => {
J
Jorge Aparicio 已提交
1307 1308
                self.word_space("box")?;
                self.print_expr(expr)?;
1309 1310
            }
            hir::ExprVec(ref exprs) => {
J
Jorge Aparicio 已提交
1311
                self.print_expr_vec(&exprs[..])?;
1312 1313
            }
            hir::ExprRepeat(ref element, ref count) => {
J
Jorge Aparicio 已提交
1314
                self.print_expr_repeat(&element, &count)?;
1315 1316
            }
            hir::ExprStruct(ref path, ref fields, ref wth) => {
J
Jorge Aparicio 已提交
1317
                self.print_expr_struct(path, &fields[..], wth)?;
1318 1319
            }
            hir::ExprTup(ref exprs) => {
J
Jorge Aparicio 已提交
1320
                self.print_expr_tup(&exprs[..])?;
1321 1322
            }
            hir::ExprCall(ref func, ref args) => {
J
Jorge Aparicio 已提交
1323
                self.print_expr_call(&func, &args[..])?;
1324
            }
1325
            hir::ExprMethodCall(name, ref tys, ref args) => {
J
Jorge Aparicio 已提交
1326
                self.print_expr_method_call(name, &tys[..], &args[..])?;
1327 1328
            }
            hir::ExprBinary(op, ref lhs, ref rhs) => {
J
Jorge Aparicio 已提交
1329
                self.print_expr_binary(op, &lhs, &rhs)?;
1330 1331
            }
            hir::ExprUnary(op, ref expr) => {
J
Jorge Aparicio 已提交
1332
                self.print_expr_unary(op, &expr)?;
1333 1334
            }
            hir::ExprAddrOf(m, ref expr) => {
J
Jorge Aparicio 已提交
1335
                self.print_expr_addr_of(m, &expr)?;
1336 1337
            }
            hir::ExprLit(ref lit) => {
J
Jorge Aparicio 已提交
1338
                self.print_literal(&lit)?;
1339 1340
            }
            hir::ExprCast(ref expr, ref ty) => {
J
Jorge Aparicio 已提交
1341 1342 1343 1344
                self.print_expr(&expr)?;
                space(&mut self.s)?;
                self.word_space("as")?;
                self.print_type(&ty)?;
1345
            }
1346
            hir::ExprType(ref expr, ref ty) => {
J
Jorge Aparicio 已提交
1347 1348 1349
                self.print_expr(&expr)?;
                self.word_space(":")?;
                self.print_type(&ty)?;
1350
            }
1351
            hir::ExprIf(ref test, ref blk, ref elseopt) => {
J
Jorge Aparicio 已提交
1352
                self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
1353
            }
1354 1355 1356
            hir::ExprWhile(ref test, ref blk, opt_sp_name) => {
                if let Some(sp_name) = opt_sp_name {
                    self.print_name(sp_name.node)?;
J
Jorge Aparicio 已提交
1357
                    self.word_space(":")?;
1358
                }
J
Jorge Aparicio 已提交
1359 1360 1361 1362
                self.head("while")?;
                self.print_expr(&test)?;
                space(&mut self.s)?;
                self.print_block(&blk)?;
1363
            }
1364 1365 1366
            hir::ExprLoop(ref blk, opt_sp_name) => {
                if let Some(sp_name) = opt_sp_name {
                    self.print_name(sp_name.node)?;
J
Jorge Aparicio 已提交
1367
                    self.word_space(":")?;
1368
                }
J
Jorge Aparicio 已提交
1369 1370 1371
                self.head("loop")?;
                space(&mut self.s)?;
                self.print_block(&blk)?;
1372 1373
            }
            hir::ExprMatch(ref expr, ref arms, _) => {
J
Jorge Aparicio 已提交
1374 1375 1376 1377 1378 1379
                self.cbox(indent_unit)?;
                self.ibox(4)?;
                self.word_nbsp("match")?;
                self.print_expr(&expr)?;
                space(&mut self.s)?;
                self.bopen()?;
1380
                for arm in arms {
J
Jorge Aparicio 已提交
1381
                    self.print_arm(arm)?;
1382
                }
J
Jorge Aparicio 已提交
1383
                self.bclose_(expr.span, indent_unit)?;
1384
            }
1385
            hir::ExprClosure(capture_clause, ref decl, ref body, _fn_decl_span) => {
J
Jorge Aparicio 已提交
1386
                self.print_capture_clause(capture_clause)?;
1387

J
Jorge Aparicio 已提交
1388 1389
                self.print_fn_block_args(&decl)?;
                space(&mut self.s)?;
1390 1391 1392

                let default_return = match decl.output {
                    hir::DefaultReturn(..) => true,
N
Nick Cameron 已提交
1393
                    _ => false,
1394 1395 1396
                };

                if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
J
Jorge Aparicio 已提交
1397
                    self.print_block_unclosed(&body)?;
1398 1399 1400 1401
                } else {
                    // we extract the block, so as not to create another set of boxes
                    match body.expr.as_ref().unwrap().node {
                        hir::ExprBlock(ref blk) => {
J
Jorge Aparicio 已提交
1402
                            self.print_block_unclosed(&blk)?;
1403 1404 1405
                        }
                        _ => {
                            // this is a bare expression
J
Jorge Aparicio 已提交
1406 1407
                            self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())?;
                            self.end()?; // need to close a box
1408 1409 1410 1411 1412 1413
                        }
                    }
                }
                // a box will be closed by print_expr, but we didn't want an overall
                // wrapper so we closed the corresponding opening. so create an
                // empty box to satisfy the close.
J
Jorge Aparicio 已提交
1414
                self.ibox(0)?;
1415 1416 1417
            }
            hir::ExprBlock(ref blk) => {
                // containing cbox, will be closed by print-block at }
J
Jorge Aparicio 已提交
1418
                self.cbox(indent_unit)?;
1419
                // head-box, will be closed by print-block after {
J
Jorge Aparicio 已提交
1420 1421
                self.ibox(0)?;
                self.print_block(&blk)?;
1422 1423
            }
            hir::ExprAssign(ref lhs, ref rhs) => {
J
Jorge Aparicio 已提交
1424 1425 1426 1427
                self.print_expr(&lhs)?;
                space(&mut self.s)?;
                self.word_space("=")?;
                self.print_expr(&rhs)?;
1428 1429
            }
            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
J
Jorge Aparicio 已提交
1430 1431
                self.print_expr(&lhs)?;
                space(&mut self.s)?;
1432
                word(&mut self.s, op.node.as_str())?;
J
Jorge Aparicio 已提交
1433 1434
                self.word_space("=")?;
                self.print_expr(&rhs)?;
1435
            }
1436
            hir::ExprField(ref expr, name) => {
J
Jorge Aparicio 已提交
1437 1438 1439
                self.print_expr(&expr)?;
                word(&mut self.s, ".")?;
                self.print_name(name.node)?;
1440 1441
            }
            hir::ExprTupField(ref expr, id) => {
J
Jorge Aparicio 已提交
1442 1443 1444
                self.print_expr(&expr)?;
                word(&mut self.s, ".")?;
                self.print_usize(id.node)?;
1445 1446
            }
            hir::ExprIndex(ref expr, ref index) => {
J
Jorge Aparicio 已提交
1447 1448 1449 1450
                self.print_expr(&expr)?;
                word(&mut self.s, "[")?;
                self.print_expr(&index)?;
                word(&mut self.s, "]")?;
1451 1452
            }
            hir::ExprPath(None, ref path) => {
J
Jorge Aparicio 已提交
1453
                self.print_path(path, true, 0)?
1454 1455
            }
            hir::ExprPath(Some(ref qself), ref path) => {
J
Jorge Aparicio 已提交
1456
                self.print_qpath(path, qself, true)?
1457
            }
V
Vadim Petrochenkov 已提交
1458
            hir::ExprBreak(opt_name) => {
J
Jorge Aparicio 已提交
1459 1460
                word(&mut self.s, "break")?;
                space(&mut self.s)?;
V
Vadim Petrochenkov 已提交
1461 1462
                if let Some(name) = opt_name {
                    self.print_name(name.node)?;
J
Jorge Aparicio 已提交
1463
                    space(&mut self.s)?;
1464 1465
                }
            }
V
Vadim Petrochenkov 已提交
1466
            hir::ExprAgain(opt_name) => {
J
Jorge Aparicio 已提交
1467 1468
                word(&mut self.s, "continue")?;
                space(&mut self.s)?;
V
Vadim Petrochenkov 已提交
1469 1470
                if let Some(name) = opt_name {
                    self.print_name(name.node)?;
J
Jorge Aparicio 已提交
1471
                    space(&mut self.s)?
1472 1473 1474
                }
            }
            hir::ExprRet(ref result) => {
J
Jorge Aparicio 已提交
1475
                word(&mut self.s, "return")?;
1476 1477
                match *result {
                    Some(ref expr) => {
J
Jorge Aparicio 已提交
1478 1479
                        word(&mut self.s, " ")?;
                        self.print_expr(&expr)?;
1480
                    }
N
Nick Cameron 已提交
1481
                    _ => (),
1482 1483
                }
            }
1484
            hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => {
J
Jorge Aparicio 已提交
1485 1486 1487 1488
                word(&mut self.s, "asm!")?;
                self.popen()?;
                self.print_string(&a.asm, a.asm_str_style)?;
                self.word_space(":")?;
1489

1490
                let mut out_idx = 0;
J
Jorge Aparicio 已提交
1491
                self.commasep(Inconsistent, &a.outputs, |s, out| {
1492 1493 1494 1495 1496
                    let mut ch = out.constraint.chars();
                    match ch.next() {
                        Some('=') if out.is_rw => {
                            s.print_string(&format!("+{}", ch.as_str()),
                                           ast::StrStyle::Cooked)?
J
Jose Narvaez 已提交
1497
                        }
1498 1499
                        _ => s.print_string(&out.constraint,
                                            ast::StrStyle::Cooked)?,
J
Jose Narvaez 已提交
1500
                    }
J
Jorge Aparicio 已提交
1501 1502 1503
                    s.popen()?;
                    s.print_expr(&outputs[out_idx])?;
                    s.pclose()?;
1504
                    out_idx += 1;
J
Jose Narvaez 已提交
1505
                    Ok(())
J
Jorge Aparicio 已提交
1506 1507 1508
                })?;
                space(&mut self.s)?;
                self.word_space(":")?;
1509

1510
                let mut in_idx = 0;
J
Jorge Aparicio 已提交
1511 1512 1513 1514 1515
                self.commasep(Inconsistent, &a.inputs, |s, co| {
                    s.print_string(&co, ast::StrStyle::Cooked)?;
                    s.popen()?;
                    s.print_expr(&inputs[in_idx])?;
                    s.pclose()?;
1516
                    in_idx += 1;
J
Jose Narvaez 已提交
1517
                    Ok(())
J
Jorge Aparicio 已提交
1518 1519 1520
                })?;
                space(&mut self.s)?;
                self.word_space(":")?;
1521

J
Jorge Aparicio 已提交
1522 1523
                self.commasep(Inconsistent, &a.clobbers, |s, co| {
                    s.print_string(&co, ast::StrStyle::Cooked)?;
J
Jose Narvaez 已提交
1524
                    Ok(())
J
Jorge Aparicio 已提交
1525
                })?;
1526

J
Jose Narvaez 已提交
1527
                let mut options = vec![];
1528 1529 1530 1531 1532 1533
                if a.volatile {
                    options.push("volatile");
                }
                if a.alignstack {
                    options.push("alignstack");
                }
1534
                if a.dialect == ast::AsmDialect::Intel {
1535 1536 1537 1538
                    options.push("intel");
                }

                if !options.is_empty() {
J
Jorge Aparicio 已提交
1539 1540 1541 1542
                    space(&mut self.s)?;
                    self.word_space(":")?;
                    self.commasep(Inconsistent, &options, |s, &co| {
                        s.print_string(co, ast::StrStyle::Cooked)?;
J
Jose Narvaez 已提交
1543
                        Ok(())
J
Jorge Aparicio 已提交
1544
                    })?;
1545 1546
                }

J
Jorge Aparicio 已提交
1547
                self.pclose()?;
1548 1549
            }
        }
J
Jorge Aparicio 已提交
1550
        self.ann.post(self, NodeExpr(expr))?;
1551 1552 1553 1554
        self.end()
    }

    pub fn print_local_decl(&mut self, loc: &hir::Local) -> io::Result<()> {
J
Jorge Aparicio 已提交
1555
        self.print_pat(&loc.pat)?;
1556
        if let Some(ref ty) = loc.ty {
J
Jorge Aparicio 已提交
1557 1558
            self.word_space(":")?;
            self.print_type(&ty)?;
1559 1560 1561 1562 1563
        }
        Ok(())
    }

    pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
J
Jorge Aparicio 已提交
1564
        self.maybe_print_comment(decl.span.lo)?;
1565 1566
        match decl.node {
            hir::DeclLocal(ref loc) => {
J
Jorge Aparicio 已提交
1567 1568 1569
                self.space_if_not_bol()?;
                self.ibox(indent_unit)?;
                self.word_nbsp("let")?;
1570

J
Jorge Aparicio 已提交
1571 1572 1573
                self.ibox(indent_unit)?;
                self.print_local_decl(&loc)?;
                self.end()?;
1574
                if let Some(ref init) = loc.init {
J
Jorge Aparicio 已提交
1575 1576 1577
                    self.nbsp()?;
                    self.word_space("=")?;
                    self.print_expr(&init)?;
1578 1579 1580
                }
                self.end()
            }
1581 1582 1583
            hir::DeclItem(ref item) => {
                self.print_item_id(item)
            }
1584 1585 1586 1587 1588 1589 1590 1591
        }
    }

    pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
        word(&mut self.s, &i.to_string())
    }

    pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
J
Jorge Aparicio 已提交
1592
        word(&mut self.s, &name.as_str())?;
1593 1594 1595
        self.ann.post(self, NodeName(&name))
    }

N
Nick Cameron 已提交
1596
    pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> {
J
Jorge Aparicio 已提交
1597 1598 1599
        self.print_local_decl(loc)?;
        space(&mut self.s)?;
        self.word_space("in")?;
1600 1601 1602 1603 1604 1605 1606
        self.print_expr(coll)
    }

    fn print_path(&mut self,
                  path: &hir::Path,
                  colons_before_params: bool,
                  depth: usize)
N
Nick Cameron 已提交
1607
                  -> io::Result<()> {
J
Jorge Aparicio 已提交
1608
        self.maybe_print_comment(path.span.lo)?;
1609 1610

        let mut first = !path.global;
J
Jose Narvaez 已提交
1611
        for segment in &path.segments[..path.segments.len() - depth] {
1612 1613 1614
            if first {
                first = false
            } else {
J
Jorge Aparicio 已提交
1615
                word(&mut self.s, "::")?
1616 1617
            }

V
Vadim Petrochenkov 已提交
1618
            self.print_name(segment.name)?;
1619

J
Jorge Aparicio 已提交
1620
            self.print_path_parameters(&segment.parameters, colons_before_params)?;
1621 1622 1623 1624 1625 1626 1627 1628 1629
        }

        Ok(())
    }

    fn print_qpath(&mut self,
                   path: &hir::Path,
                   qself: &hir::QSelf,
                   colons_before_params: bool)
N
Nick Cameron 已提交
1630
                   -> io::Result<()> {
J
Jorge Aparicio 已提交
1631 1632
        word(&mut self.s, "<")?;
        self.print_type(&qself.ty)?;
1633
        if qself.position > 0 {
J
Jorge Aparicio 已提交
1634 1635
            space(&mut self.s)?;
            self.word_space("as")?;
1636
            let depth = path.segments.len() - qself.position;
J
Jorge Aparicio 已提交
1637
            self.print_path(&path, false, depth)?;
1638
        }
J
Jorge Aparicio 已提交
1639 1640
        word(&mut self.s, ">")?;
        word(&mut self.s, "::")?;
1641
        let item_segment = path.segments.last().unwrap();
V
Vadim Petrochenkov 已提交
1642
        self.print_name(item_segment.name)?;
1643 1644 1645 1646 1647 1648
        self.print_path_parameters(&item_segment.parameters, colons_before_params)
    }

    fn print_path_parameters(&mut self,
                             parameters: &hir::PathParameters,
                             colons_before_params: bool)
N
Nick Cameron 已提交
1649
                             -> io::Result<()> {
1650 1651 1652 1653 1654
        if parameters.is_empty() {
            return Ok(());
        }

        if colons_before_params {
J
Jorge Aparicio 已提交
1655
            word(&mut self.s, "::")?
1656 1657 1658 1659
        }

        match *parameters {
            hir::AngleBracketedParameters(ref data) => {
J
Jorge Aparicio 已提交
1660
                word(&mut self.s, "<")?;
1661 1662 1663 1664

                let mut comma = false;
                for lifetime in &data.lifetimes {
                    if comma {
J
Jorge Aparicio 已提交
1665
                        self.word_space(",")?
1666
                    }
J
Jorge Aparicio 已提交
1667
                    self.print_lifetime(lifetime)?;
1668 1669 1670 1671 1672
                    comma = true;
                }

                if !data.types.is_empty() {
                    if comma {
J
Jorge Aparicio 已提交
1673
                        self.word_space(",")?
1674
                    }
J
Jorge Aparicio 已提交
1675
                    self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?;
N
Nick Cameron 已提交
1676
                    comma = true;
1677 1678 1679 1680
                }

                for binding in data.bindings.iter() {
                    if comma {
J
Jorge Aparicio 已提交
1681
                        self.word_space(",")?
1682
                    }
J
Jorge Aparicio 已提交
1683 1684 1685 1686
                    self.print_name(binding.name)?;
                    space(&mut self.s)?;
                    self.word_space("=")?;
                    self.print_type(&binding.ty)?;
1687 1688 1689
                    comma = true;
                }

J
Jorge Aparicio 已提交
1690
                word(&mut self.s, ">")?
1691 1692 1693
            }

            hir::ParenthesizedParameters(ref data) => {
J
Jorge Aparicio 已提交
1694 1695 1696
                word(&mut self.s, "(")?;
                self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?;
                word(&mut self.s, ")")?;
1697 1698

                match data.output {
N
Nick Cameron 已提交
1699
                    None => {}
1700
                    Some(ref ty) => {
J
Jorge Aparicio 已提交
1701 1702 1703
                        self.space_if_not_bol()?;
                        self.word_space("->")?;
                        self.print_type(&ty)?;
1704 1705 1706 1707 1708 1709 1710 1711 1712
                    }
                }
            }
        }

        Ok(())
    }

    pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
J
Jorge Aparicio 已提交
1713 1714
        self.maybe_print_comment(pat.span.lo)?;
        self.ann.pre(self, NodePat(pat))?;
J
Jose Narvaez 已提交
1715 1716
        // Pat isn't normalized, but the beauty of it
        // is that it doesn't matter
1717
        match pat.node {
J
Jorge Aparicio 已提交
1718
            PatKind::Wild => word(&mut self.s, "_")?,
1719
            PatKind::Binding(binding_mode, ref path1, ref sub) => {
1720 1721
                match binding_mode {
                    hir::BindByRef(mutbl) => {
J
Jorge Aparicio 已提交
1722 1723
                        self.word_nbsp("ref")?;
                        self.print_mutability(mutbl)?;
1724 1725 1726
                    }
                    hir::BindByValue(hir::MutImmutable) => {}
                    hir::BindByValue(hir::MutMutable) => {
J
Jorge Aparicio 已提交
1727
                        self.word_nbsp("mut")?;
1728 1729
                    }
                }
V
Vadim Petrochenkov 已提交
1730
                self.print_name(path1.node)?;
1731 1732 1733
                if let Some(ref p) = *sub {
                    word(&mut self.s, "@")?;
                    self.print_pat(&p)?;
1734 1735
                }
            }
1736
            PatKind::TupleStruct(ref path, ref elts, ddpos) => {
J
Jorge Aparicio 已提交
1737
                self.print_path(path, true, 0)?;
1738 1739 1740 1741 1742 1743 1744 1745 1746 1747
                self.popen()?;
                if let Some(ddpos) = ddpos {
                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
                    if ddpos != 0 {
                        self.word_space(",")?;
                    }
                    word(&mut self.s, "..")?;
                    if ddpos != elts.len() {
                        word(&mut self.s, ",")?;
                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
1748
                    }
1749 1750
                } else {
                    try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)));
1751
                }
1752
                try!(self.pclose());
1753
            }
1754
            PatKind::Path(ref path) => {
J
Jorge Aparicio 已提交
1755
                self.print_path(path, true, 0)?;
1756
            }
1757
            PatKind::QPath(ref qself, ref path) => {
J
Jorge Aparicio 已提交
1758
                self.print_qpath(path, qself, false)?;
1759
            }
1760
            PatKind::Struct(ref path, ref fields, etc) => {
J
Jorge Aparicio 已提交
1761 1762 1763 1764
                self.print_path(path, true, 0)?;
                self.nbsp()?;
                self.word_space("{")?;
                self.commasep_cmnt(Consistent,
J
Jorge Aparicio 已提交
1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775
                                   &fields[..],
                                   |s, f| {
                                       s.cbox(indent_unit)?;
                                       if !f.node.is_shorthand {
                                           s.print_name(f.node.name)?;
                                           s.word_nbsp(":")?;
                                       }
                                       s.print_pat(&f.node.pat)?;
                                       s.end()
                                   },
                                   |f| f.node.pat.span)?;
1776
                if etc {
N
Nick Cameron 已提交
1777
                    if !fields.is_empty() {
J
Jorge Aparicio 已提交
1778
                        self.word_space(",")?;
N
Nick Cameron 已提交
1779
                    }
J
Jorge Aparicio 已提交
1780
                    word(&mut self.s, "..")?;
1781
                }
J
Jorge Aparicio 已提交
1782 1783
                space(&mut self.s)?;
                word(&mut self.s, "}")?;
1784
            }
1785
            PatKind::Tuple(ref elts, ddpos) => {
J
Jorge Aparicio 已提交
1786
                self.popen()?;
1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801
                if let Some(ddpos) = ddpos {
                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
                    if ddpos != 0 {
                        self.word_space(",")?;
                    }
                    word(&mut self.s, "..")?;
                    if ddpos != elts.len() {
                        word(&mut self.s, ",")?;
                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
                    }
                } else {
                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
                    if elts.len() == 1 {
                        word(&mut self.s, ",")?;
                    }
1802
                }
J
Jorge Aparicio 已提交
1803
                self.pclose()?;
1804
            }
1805
            PatKind::Box(ref inner) => {
J
Jorge Aparicio 已提交
1806 1807
                word(&mut self.s, "box ")?;
                self.print_pat(&inner)?;
1808
            }
1809
            PatKind::Ref(ref inner, mutbl) => {
J
Jorge Aparicio 已提交
1810
                word(&mut self.s, "&")?;
1811
                if mutbl == hir::MutMutable {
J
Jorge Aparicio 已提交
1812
                    word(&mut self.s, "mut ")?;
1813
                }
J
Jorge Aparicio 已提交
1814
                self.print_pat(&inner)?;
1815
            }
J
Jorge Aparicio 已提交
1816
            PatKind::Lit(ref e) => self.print_expr(&e)?,
1817
            PatKind::Range(ref begin, ref end) => {
J
Jorge Aparicio 已提交
1818 1819 1820 1821
                self.print_expr(&begin)?;
                space(&mut self.s)?;
                word(&mut self.s, "...")?;
                self.print_expr(&end)?;
1822
            }
1823
            PatKind::Vec(ref before, ref slice, ref after) => {
J
Jorge Aparicio 已提交
1824 1825
                word(&mut self.s, "[")?;
                self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))?;
1826
                if let Some(ref p) = *slice {
N
Nick Cameron 已提交
1827
                    if !before.is_empty() {
J
Jorge Aparicio 已提交
1828
                        self.word_space(",")?;
N
Nick Cameron 已提交
1829
                    }
1830
                    if p.node != PatKind::Wild {
J
Jorge Aparicio 已提交
1831
                        self.print_pat(&p)?;
1832
                    }
J
Jorge Aparicio 已提交
1833
                    word(&mut self.s, "..")?;
N
Nick Cameron 已提交
1834
                    if !after.is_empty() {
J
Jorge Aparicio 已提交
1835
                        self.word_space(",")?;
N
Nick Cameron 已提交
1836
                    }
1837
                }
J
Jorge Aparicio 已提交
1838 1839
                self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p))?;
                word(&mut self.s, "]")?;
1840 1841 1842 1843 1844 1845 1846 1847 1848
            }
        }
        self.ann.post(self, NodePat(pat))
    }

    fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
        // I have no idea why this check is necessary, but here it
        // is :(
        if arm.attrs.is_empty() {
J
Jorge Aparicio 已提交
1849
            space(&mut self.s)?;
1850
        }
J
Jorge Aparicio 已提交
1851 1852 1853
        self.cbox(indent_unit)?;
        self.ibox(0)?;
        self.print_outer_attributes(&arm.attrs)?;
1854 1855 1856 1857 1858
        let mut first = true;
        for p in &arm.pats {
            if first {
                first = false;
            } else {
J
Jorge Aparicio 已提交
1859 1860
                space(&mut self.s)?;
                self.word_space("|")?;
1861
            }
J
Jorge Aparicio 已提交
1862
            self.print_pat(&p)?;
1863
        }
J
Jorge Aparicio 已提交
1864
        space(&mut self.s)?;
1865
        if let Some(ref e) = arm.guard {
J
Jorge Aparicio 已提交
1866 1867 1868
            self.word_space("if")?;
            self.print_expr(&e)?;
            space(&mut self.s)?;
1869
        }
J
Jorge Aparicio 已提交
1870
        self.word_space("=>")?;
1871 1872 1873 1874

        match arm.body.node {
            hir::ExprBlock(ref blk) => {
                // the block will close the pattern's ibox
J
Jorge Aparicio 已提交
1875
                self.print_block_unclosed_indent(&blk, indent_unit)?;
1876 1877 1878

                // If it is a user-provided unsafe block, print a comma after it
                if let hir::UnsafeBlock(hir::UserProvided) = blk.rules {
J
Jorge Aparicio 已提交
1879
                    word(&mut self.s, ",")?;
1880 1881 1882
                }
            }
            _ => {
J
Jorge Aparicio 已提交
1883 1884 1885
                self.end()?; // close the ibox for the pattern
                self.print_expr(&arm.body)?;
                word(&mut self.s, ",")?;
1886 1887 1888 1889 1890
            }
        }
        self.end() // close enclosing cbox
    }

1891 1892 1893 1894 1895
    fn print_explicit_self(&mut self, explicit_self: &hir::ExplicitSelf) -> io::Result<()> {
        match explicit_self.node {
            SelfKind::Value(m) => {
                self.print_mutability(m)?;
                word(&mut self.s, "self")
1896
            }
1897
            SelfKind::Region(ref lt, m) => {
J
Jorge Aparicio 已提交
1898 1899 1900
                word(&mut self.s, "&")?;
                self.print_opt_lifetime(lt)?;
                self.print_mutability(m)?;
1901
                word(&mut self.s, "self")
1902
            }
1903 1904
            SelfKind::Explicit(ref typ, m) => {
                self.print_mutability(m)?;
J
Jorge Aparicio 已提交
1905 1906
                word(&mut self.s, "self")?;
                self.word_space(":")?;
1907
                self.print_type(&typ)
1908 1909 1910 1911 1912 1913 1914 1915
            }
        }
    }

    pub fn print_fn(&mut self,
                    decl: &hir::FnDecl,
                    unsafety: hir::Unsafety,
                    constness: hir::Constness,
1916
                    abi: Abi,
V
Vadim Petrochenkov 已提交
1917
                    name: Option<ast::Name>,
1918
                    generics: &hir::Generics,
1919
                    vis: &hir::Visibility)
N
Nick Cameron 已提交
1920
                    -> io::Result<()> {
J
Jorge Aparicio 已提交
1921
        self.print_fn_header_info(unsafety, constness, abi, vis)?;
1922 1923

        if let Some(name) = name {
J
Jorge Aparicio 已提交
1924 1925
            self.nbsp()?;
            self.print_name(name)?;
1926
        }
J
Jorge Aparicio 已提交
1927
        self.print_generics(generics)?;
1928
        self.print_fn_args_and_ret(decl)?;
1929 1930 1931
        self.print_where_clause(&generics.where_clause)
    }

1932
    pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
J
Jorge Aparicio 已提交
1933
        self.popen()?;
1934
        self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
1935
        if decl.variadic {
J
Jorge Aparicio 已提交
1936
            word(&mut self.s, ", ...")?;
1937
        }
J
Jorge Aparicio 已提交
1938
        self.pclose()?;
1939 1940 1941 1942

        self.print_fn_output(decl)
    }

N
Nick Cameron 已提交
1943
    pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
J
Jorge Aparicio 已提交
1944
        word(&mut self.s, "|")?;
1945
        self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?;
J
Jorge Aparicio 已提交
1946
        word(&mut self.s, "|")?;
1947 1948 1949 1950 1951

        if let hir::DefaultReturn(..) = decl.output {
            return Ok(());
        }

J
Jorge Aparicio 已提交
1952 1953
        self.space_if_not_bol()?;
        self.word_space("->")?;
1954 1955
        match decl.output {
            hir::Return(ref ty) => {
J
Jorge Aparicio 已提交
1956
                self.print_type(&ty)?;
1957 1958 1959 1960
                self.maybe_print_comment(ty.span.lo)
            }
            hir::DefaultReturn(..) => unreachable!(),
            hir::NoReturn(span) => {
J
Jorge Aparicio 已提交
1961
                self.word_nbsp("!")?;
1962 1963 1964 1965 1966
                self.maybe_print_comment(span.lo)
            }
        }
    }

N
Nick Cameron 已提交
1967
    pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) -> io::Result<()> {
1968 1969 1970 1971 1972 1973
        match capture_clause {
            hir::CaptureByValue => self.word_space("move"),
            hir::CaptureByRef => Ok(()),
        }
    }

N
Nick Cameron 已提交
1974
    pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> {
1975
        if !bounds.is_empty() {
J
Jorge Aparicio 已提交
1976
            word(&mut self.s, prefix)?;
1977 1978
            let mut first = true;
            for bound in bounds {
J
Jorge Aparicio 已提交
1979
                self.nbsp()?;
1980 1981 1982
                if first {
                    first = false;
                } else {
J
Jorge Aparicio 已提交
1983
                    self.word_space("+")?;
1984 1985
                }

J
Jorge Aparicio 已提交
1986
                match *bound {
1987 1988 1989 1990
                    TraitTyParamBound(ref tref, TraitBoundModifier::None) => {
                        self.print_poly_trait_ref(tref)
                    }
                    TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => {
J
Jorge Aparicio 已提交
1991
                        word(&mut self.s, "?")?;
1992 1993 1994 1995 1996
                        self.print_poly_trait_ref(tref)
                    }
                    RegionTyParamBound(ref lt) => {
                        self.print_lifetime(lt)
                    }
J
Jorge Aparicio 已提交
1997
                }?
1998 1999 2000 2001 2002 2003 2004
            }
            Ok(())
        } else {
            Ok(())
        }
    }

N
Nick Cameron 已提交
2005
    pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
2006 2007 2008
        self.print_name(lifetime.name)
    }

N
Nick Cameron 已提交
2009
    pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> {
J
Jorge Aparicio 已提交
2010
        self.print_lifetime(&lifetime.lifetime)?;
2011 2012
        let mut sep = ":";
        for v in &lifetime.bounds {
J
Jorge Aparicio 已提交
2013 2014
            word(&mut self.s, sep)?;
            self.print_lifetime(v)?;
2015 2016 2017 2018 2019
            sep = "+";
        }
        Ok(())
    }

N
Nick Cameron 已提交
2020
    pub fn print_generics(&mut self, generics: &hir::Generics) -> io::Result<()> {
2021 2022 2023 2024 2025
        let total = generics.lifetimes.len() + generics.ty_params.len();
        if total == 0 {
            return Ok(());
        }

J
Jorge Aparicio 已提交
2026
        word(&mut self.s, "<")?;
2027 2028 2029 2030 2031 2032

        let mut ints = Vec::new();
        for i in 0..total {
            ints.push(i);
        }

J
Jorge Aparicio 已提交
2033
        self.commasep(Inconsistent, &ints[..], |s, &idx| {
J
Jose Narvaez 已提交
2034 2035 2036 2037 2038 2039 2040 2041
            if idx < generics.lifetimes.len() {
                let lifetime = &generics.lifetimes[idx];
                s.print_lifetime_def(lifetime)
            } else {
                let idx = idx - generics.lifetimes.len();
                let param = &generics.ty_params[idx];
                s.print_ty_param(param)
            }
J
Jorge Aparicio 已提交
2042
        })?;
2043

J
Jorge Aparicio 已提交
2044
        word(&mut self.s, ">")?;
2045 2046 2047 2048
        Ok(())
    }

    pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> {
J
Jorge Aparicio 已提交
2049 2050
        self.print_name(param.name)?;
        self.print_bounds(":", &param.bounds)?;
2051 2052
        match param.default {
            Some(ref default) => {
J
Jorge Aparicio 已提交
2053 2054
                space(&mut self.s)?;
                self.word_space("=")?;
2055
                self.print_type(&default)
2056
            }
N
Nick Cameron 已提交
2057
            _ => Ok(()),
2058 2059 2060
        }
    }

N
Nick Cameron 已提交
2061
    pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> {
2062
        if where_clause.predicates.is_empty() {
J
Jose Narvaez 已提交
2063
            return Ok(());
2064 2065
        }

J
Jorge Aparicio 已提交
2066 2067
        space(&mut self.s)?;
        self.word_space("where")?;
2068 2069 2070

        for (i, predicate) in where_clause.predicates.iter().enumerate() {
            if i != 0 {
J
Jorge Aparicio 已提交
2071
                self.word_space(",")?;
2072 2073 2074 2075 2076 2077 2078
            }

            match predicate {
                &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bound_lifetimes,
                                                                              ref bounded_ty,
                                                                              ref bounds,
                                                                              ..}) => {
J
Jorge Aparicio 已提交
2079 2080 2081
                    self.print_formal_lifetime_list(bound_lifetimes)?;
                    self.print_type(&bounded_ty)?;
                    self.print_bounds(":", bounds)?;
2082 2083 2084 2085
                }
                &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
                                                                                ref bounds,
                                                                                ..}) => {
J
Jorge Aparicio 已提交
2086 2087
                    self.print_lifetime(lifetime)?;
                    word(&mut self.s, ":")?;
2088 2089

                    for (i, bound) in bounds.iter().enumerate() {
J
Jorge Aparicio 已提交
2090
                        self.print_lifetime(bound)?;
2091 2092

                        if i != 0 {
J
Jorge Aparicio 已提交
2093
                            word(&mut self.s, ":")?;
2094 2095 2096 2097
                        }
                    }
                }
                &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => {
J
Jorge Aparicio 已提交
2098 2099 2100 2101
                    self.print_path(path, false, 0)?;
                    space(&mut self.s)?;
                    self.word_space("=")?;
                    self.print_type(&ty)?;
2102 2103 2104 2105 2106 2107 2108 2109 2110
                }
            }
        }

        Ok(())
    }

    pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
        match vp.node {
2111
            hir::ViewPathSimple(name, ref path) => {
J
Jorge Aparicio 已提交
2112
                self.print_path(path, false, 0)?;
2113

V
Vadim Petrochenkov 已提交
2114
                if path.segments.last().unwrap().name != name {
J
Jorge Aparicio 已提交
2115 2116 2117
                    space(&mut self.s)?;
                    self.word_space("as")?;
                    self.print_name(name)?;
2118 2119 2120 2121 2122 2123
                }

                Ok(())
            }

            hir::ViewPathGlob(ref path) => {
J
Jorge Aparicio 已提交
2124
                self.print_path(path, false, 0)?;
2125 2126 2127
                word(&mut self.s, "::*")
            }

2128
            hir::ViewPathList(ref path, ref segments) => {
2129
                if path.segments.is_empty() {
J
Jorge Aparicio 已提交
2130
                    word(&mut self.s, "{")?;
2131
                } else {
J
Jorge Aparicio 已提交
2132 2133
                    self.print_path(path, false, 0)?;
                    word(&mut self.s, "::{")?;
2134
                }
J
Jorge Aparicio 已提交
2135
                self.commasep(Inconsistent, &segments[..], |s, w| {
J
Jose Narvaez 已提交
2136 2137 2138 2139 2140 2141 2142 2143
                    match w.node {
                        hir::PathListIdent { name, .. } => {
                            s.print_name(name)
                        }
                        hir::PathListMod { .. } => {
                            word(&mut s.s, "self")
                        }
                    }
J
Jorge Aparicio 已提交
2144
                })?;
2145 2146 2147 2148 2149
                word(&mut self.s, "}")
            }
        }
    }

N
Nick Cameron 已提交
2150
    pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> {
2151 2152 2153 2154 2155 2156 2157
        match mutbl {
            hir::MutMutable => self.word_nbsp("mut"),
            hir::MutImmutable => Ok(()),
        }
    }

    pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> {
J
Jorge Aparicio 已提交
2158
        self.print_mutability(mt.mutbl)?;
2159
        self.print_type(&mt.ty)
2160 2161
    }

2162
    pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> {
J
Jorge Aparicio 已提交
2163
        self.ibox(indent_unit)?;
2164
        match input.ty.node {
J
Jorge Aparicio 已提交
2165
            hir::TyInfer if is_closure => self.print_pat(&input.pat)?,
2166
            _ => {
2167 2168 2169
                if let Some(eself) = input.to_self() {
                    self.print_explicit_self(&eself)?;
                } else {
2170
                    let invalid = if let PatKind::Binding(_, name, _) = input.pat.node {
V
Vadim Petrochenkov 已提交
2171
                        name.node == keywords::Invalid.name()
2172 2173 2174 2175
                    } else {
                        false
                    };
                    if !invalid {
J
Jorge Aparicio 已提交
2176 2177 2178
                        self.print_pat(&input.pat)?;
                        word(&mut self.s, ":")?;
                        space(&mut self.s)?;
2179
                    }
2180
                    self.print_type(&input.ty)?;
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191
                }
            }
        }
        self.end()
    }

    pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
        if let hir::DefaultReturn(..) = decl.output {
            return Ok(());
        }

J
Jorge Aparicio 已提交
2192 2193 2194
        self.space_if_not_bol()?;
        self.ibox(indent_unit)?;
        self.word_space("->")?;
2195
        match decl.output {
J
Jorge Aparicio 已提交
2196
            hir::NoReturn(_) => self.word_nbsp("!")?,
2197
            hir::DefaultReturn(..) => unreachable!(),
J
Jorge Aparicio 已提交
2198
            hir::Return(ref ty) => self.print_type(&ty)?,
2199
        }
J
Jorge Aparicio 已提交
2200
        self.end()?;
2201 2202 2203

        match decl.output {
            hir::Return(ref output) => self.maybe_print_comment(output.span.lo),
N
Nick Cameron 已提交
2204
            _ => Ok(()),
2205 2206 2207 2208
        }
    }

    pub fn print_ty_fn(&mut self,
2209
                       abi: Abi,
2210 2211
                       unsafety: hir::Unsafety,
                       decl: &hir::FnDecl,
2212
                       name: Option<ast::Name>,
2213
                       generics: &hir::Generics)
2214
                       -> io::Result<()> {
J
Jorge Aparicio 已提交
2215
        self.ibox(indent_unit)?;
2216
        if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
J
Jorge Aparicio 已提交
2217 2218
            word(&mut self.s, "for")?;
            self.print_generics(generics)?;
2219 2220
        }
        let generics = hir::Generics {
2221
            lifetimes: hir::HirVec::new(),
2222
            ty_params: hir::HirVec::new(),
2223 2224
            where_clause: hir::WhereClause {
                id: ast::DUMMY_NODE_ID,
2225
                predicates: hir::HirVec::new(),
2226 2227
            },
        };
J
Jorge Aparicio 已提交
2228
        self.print_fn(decl,
J
Jorge Aparicio 已提交
2229 2230 2231 2232 2233
                      unsafety,
                      hir::Constness::NotConst,
                      abi,
                      name,
                      &generics,
2234
                      &hir::Inherited)?;
2235 2236 2237
        self.end()
    }

N
Nick Cameron 已提交
2238 2239
    pub fn maybe_print_trailing_comment(&mut self,
                                        span: codemap::Span,
2240
                                        next_pos: Option<BytePos>)
N
Nick Cameron 已提交
2241
                                        -> io::Result<()> {
2242 2243
        let cm = match self.cm {
            Some(cm) => cm,
N
Nick Cameron 已提交
2244
            _ => return Ok(()),
2245
        };
2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259
        if let Some(ref cmnt) = self.next_comment() {
            if (*cmnt).style != comments::Trailing {
                return Ok(());
            }
            let span_line = cm.lookup_char_pos(span.hi);
            let comment_line = cm.lookup_char_pos((*cmnt).pos);
            let mut next = (*cmnt).pos + BytePos(1);
            if let Some(p) = next_pos {
                next = p;
            }
            if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
               span_line.line == comment_line.line {
                self.print_comment(cmnt)?;
                self.cur_cmnt_and_lit.cur_cmnt += 1;
2260 2261 2262 2263 2264 2265 2266 2267 2268
            }
        }
        Ok(())
    }

    pub fn print_remaining_comments(&mut self) -> io::Result<()> {
        // If there aren't any remaining comments, then we need to manually
        // make sure there is a line break at the end.
        if self.next_comment().is_none() {
J
Jorge Aparicio 已提交
2269
            hardbreak(&mut self.s)?;
2270 2271 2272 2273
        }
        loop {
            match self.next_comment() {
                Some(ref cmnt) => {
J
Jorge Aparicio 已提交
2274
                    self.print_comment(cmnt)?;
2275 2276
                    self.cur_cmnt_and_lit.cur_cmnt += 1;
                }
N
Nick Cameron 已提交
2277
                _ => break,
2278 2279 2280 2281 2282 2283
            }
        }
        Ok(())
    }

    pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
2284
                                                  opt_abi: Option<Abi>)
N
Nick Cameron 已提交
2285
                                                  -> io::Result<()> {
2286
        match opt_abi {
2287
            Some(Abi::Rust) => Ok(()),
2288
            Some(abi) => {
J
Jorge Aparicio 已提交
2289
                self.word_nbsp("extern")?;
2290 2291
                self.word_nbsp(&abi.to_string())
            }
N
Nick Cameron 已提交
2292
            None => Ok(()),
2293 2294 2295
        }
    }

2296
    pub fn print_extern_opt_abi(&mut self, opt_abi: Option<Abi>) -> io::Result<()> {
2297 2298
        match opt_abi {
            Some(abi) => {
J
Jorge Aparicio 已提交
2299
                self.word_nbsp("extern")?;
2300 2301
                self.word_nbsp(&abi.to_string())
            }
N
Nick Cameron 已提交
2302
            None => Ok(()),
2303 2304 2305 2306 2307 2308
        }
    }

    pub fn print_fn_header_info(&mut self,
                                unsafety: hir::Unsafety,
                                constness: hir::Constness,
2309
                                abi: Abi,
2310
                                vis: &hir::Visibility)
N
Nick Cameron 已提交
2311
                                -> io::Result<()> {
J
Jorge Aparicio 已提交
2312 2313
        word(&mut self.s, &visibility_qualified(vis, ""))?;
        self.print_unsafety(unsafety)?;
2314 2315 2316

        match constness {
            hir::Constness::NotConst => {}
J
Jorge Aparicio 已提交
2317
            hir::Constness::Const => self.word_nbsp("const")?,
2318 2319
        }

2320
        if abi != Abi::Rust {
J
Jorge Aparicio 已提交
2321 2322
            self.word_nbsp("extern")?;
            self.word_nbsp(&abi.to_string())?;
2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345
        }

        word(&mut self.s, "fn")
    }

    pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> {
        match s {
            hir::Unsafety::Normal => Ok(()),
            hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
        }
    }
}

// Dup'ed from parse::classify, but adapted for the HIR.
/// Does this expression require a semicolon to be treated
/// as a statement? The negation of this: 'can this expression
/// be used as a statement without a semicolon' -- is used
/// as an early-bail-out in the parser so that, for instance,
///     if true {...} else {...}
///      |x| 5
/// isn't parsed as (if true {...} else {...} | x) | 5
fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool {
    match e.node {
N
Nick Cameron 已提交
2346 2347 2348 2349 2350 2351
        hir::ExprIf(..) |
        hir::ExprMatch(..) |
        hir::ExprBlock(_) |
        hir::ExprWhile(..) |
        hir::ExprLoop(..) => false,
        _ => true,
2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362
    }
}

/// this statement requires a semicolon after it.
/// note that in one case (stmt_semi), we've already
/// seen the semicolon, and thus don't need another.
fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool {
    match *stmt {
        hir::StmtDecl(ref d, _) => {
            match d.node {
                hir::DeclLocal(_) => true,
N
Nick Cameron 已提交
2363
                hir::DeclItem(_) => false,
2364 2365
            }
        }
N
Nick Cameron 已提交
2366
        hir::StmtExpr(ref e, _) => {
2367
            expr_requires_semi_to_be_stmt(&e)
N
Nick Cameron 已提交
2368 2369 2370 2371
        }
        hir::StmtSemi(..) => {
            false
        }
2372 2373
    }
}