print.rs 86.5 KB
Newer Older
1
use rustc_target::spec::abi::Abi;
2
use syntax::ast;
D
Donato Sciarra 已提交
3
use syntax::source_map::{SourceMap, Spanned};
4
use syntax::parse::ParseSess;
5
use syntax::parse::lexer::comments;
6
use syntax::print::pp::{self, Breaks};
7
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
8
use syntax::print::pprust::{self, PrintState};
9
use syntax::ptr::P;
10
use syntax::symbol::kw;
11
use syntax::util::parser::{self, AssocOp, Fixity};
12
use syntax_pos::{self, BytePos, FileName};
13

M
Mark Mansi 已提交
14 15 16
use crate::hir;
use crate::hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd};
use crate::hir::{GenericParam, GenericParamKind, GenericArg};
17

18
use std::borrow::Cow;
19
use std::cell::Cell;
20
use std::io::{self, Write, Read};
21
use std::vec;
22 23

pub enum AnnNode<'a> {
V
varkor 已提交
24 25 26
    Name(&'a ast::Name),
    Block(&'a hir::Block),
    Item(&'a hir::Item),
L
ljedrz 已提交
27
    SubItem(hir::HirId),
V
varkor 已提交
28 29
    Expr(&'a hir::Expr),
    Pat(&'a hir::Pat),
30 31
}

32 33 34 35 36 37 38 39
pub enum Nested {
    Item(hir::ItemId),
    TraitItem(hir::TraitItemId),
    ImplItem(hir::ImplItemId),
    Body(hir::BodyId),
    BodyArgPat(hir::BodyId, usize)
}

40
pub trait PpAnn {
41
    fn nested(&self, _state: &mut State<'_>, _nested: Nested) -> io::Result<()> {
42 43
        Ok(())
    }
44
    fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) -> io::Result<()> {
N
Nick Cameron 已提交
45 46
        Ok(())
    }
47
    fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) -> io::Result<()> {
N
Nick Cameron 已提交
48 49
        Ok(())
    }
50
    fn try_fetch_item(&self, _: hir::HirId) -> Option<&hir::Item> {
51 52
        None
    }
53 54 55 56
}

pub struct NoAnn;
impl PpAnn for NoAnn {}
57
pub const NO_ANN: &dyn PpAnn = &NoAnn;
58 59

impl PpAnn for hir::Crate {
60
    fn try_fetch_item(&self, item: hir::HirId) -> Option<&hir::Item> {
61 62
        Some(self.item(item))
    }
63
    fn nested(&self, state: &mut State<'_>, nested: Nested) -> io::Result<()> {
64 65 66 67 68 69 70 71 72
        match nested {
            Nested::Item(id) => state.print_item(self.item(id.id)),
            Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)),
            Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)),
            Nested::Body(id) => state.print_expr(&self.body(id).value),
            Nested::BodyArgPat(id, i) => state.print_pat(&self.body(id).arguments[i].pat)
        }
    }
}
73 74 75

pub struct State<'a> {
    pub s: pp::Printer<'a>,
D
Donato Sciarra 已提交
76
    cm: Option<&'a SourceMap>,
77
    comments: Option<Vec<comments::Comment>>,
78
    cur_cmnt: usize,
79
    boxes: Vec<pp::Breaks>,
M
Manish Goregaokar 已提交
80
    ann: &'a (dyn PpAnn + 'a),
81 82
}

83 84 85 86 87 88 89 90 91 92 93 94 95
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
    }

96 97
    fn cur_cmnt(&mut self) -> &mut usize {
        &mut self.cur_cmnt
98 99 100
    }
}

101 102 103 104 105 106 107 108
#[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
109
/// it can scan the input text for comments to copy forward.
D
Donato Sciarra 已提交
110
pub fn print_crate<'a>(cm: &'a SourceMap,
111
                       sess: &ParseSess,
112
                       krate: &hir::Crate,
113
                       filename: FileName,
M
Manish Goregaokar 已提交
114 115
                       input: &mut dyn Read,
                       out: Box<dyn Write + 'a>,
116
                       ann: &'a dyn PpAnn)
N
Nick Cameron 已提交
117
                       -> io::Result<()> {
118
    let mut s = State::new_from_input(cm, sess, filename, input, out, ann);
119 120 121 122

    // 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 已提交
123 124
    s.print_mod(&krate.module, &krate.attrs)?;
    s.print_remaining_comments()?;
125
    s.s.eof()
126 127 128
}

impl<'a> State<'a> {
D
Donato Sciarra 已提交
129
    pub fn new_from_input(cm: &'a SourceMap,
130
                          sess: &ParseSess,
131
                          filename: FileName,
M
Manish Goregaokar 已提交
132 133
                          input: &mut dyn Read,
                          out: Box<dyn Write + 'a>,
134
                          ann: &'a dyn PpAnn)
N
Nick Cameron 已提交
135
                          -> State<'a> {
136 137
        let comments = comments::gather_comments(sess, filename, input);
        State::new(cm, out, ann, Some(comments))
138 139
    }

D
Donato Sciarra 已提交
140
    pub fn new(cm: &'a SourceMap,
M
Manish Goregaokar 已提交
141 142
               out: Box<dyn Write + 'a>,
               ann: &'a dyn PpAnn,
143
               comments: Option<Vec<comments::Comment>>)
N
Nick Cameron 已提交
144
               -> State<'a> {
145 146 147
        State {
            s: pp::mk_printer(out, default_columns),
            cm: Some(cm),
S
Shotaro Yamada 已提交
148
            comments,
149
            cur_cmnt: 0,
150
            boxes: Vec::new(),
151
            ann,
152 153 154 155
        }
    }
}

M
Manish Goregaokar 已提交
156
pub fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
157
    where F: FnOnce(&mut State<'_>) -> io::Result<()>
158 159 160
{
    let mut wr = Vec::new();
    {
161 162 163 164
        let mut printer = State {
            s: pp::mk_printer(Box::new(&mut wr), default_columns),
            cm: None,
            comments: None,
165
            cur_cmnt: 0,
166
            boxes: Vec::new(),
167
            ann,
168
        };
169
        f(&mut printer).unwrap();
170
        printer.s.eof().unwrap();
171 172 173 174
    }
    String::from_utf8(wr).unwrap()
}

175
pub fn visibility_qualified<S: Into<Cow<'static, str>>>(vis: &hir::Visibility, w: S) -> String {
176 177
    to_string(NO_ANN, |s| {
        s.print_visibility(vis)?;
178
        s.s.word(w)
179 180 181 182 183 184
    })
}

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

N
Nick Cameron 已提交
188
    pub fn nbsp(&mut self) -> io::Result<()> {
189
        self.s.word(" ")
N
Nick Cameron 已提交
190
    }
191

192
    pub fn word_nbsp<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
193
        self.s.word(w)?;
194 195 196
        self.nbsp()
    }

197 198
    pub fn head<S: Into<Cow<'static, str>>>(&mut self, w: S) -> io::Result<()> {
        let w = w.into();
199
        // outer-box is consistent
J
Jorge Aparicio 已提交
200
        self.cbox(indent_unit)?;
201
        // head-box is inconsistent
J
Jorge Aparicio 已提交
202
        self.ibox(w.len() + 1)?;
203 204
        // keyword that starts the head
        if !w.is_empty() {
J
Jorge Aparicio 已提交
205
            self.word_nbsp(w)?;
206 207 208 209 210
        }
        Ok(())
    }

    pub fn bopen(&mut self) -> io::Result<()> {
211
        self.s.word("{")?;
212 213 214
        self.end() // close the head-box
    }

215
    pub fn bclose_(&mut self, span: syntax_pos::Span, indented: usize) -> io::Result<()> {
216 217
        self.bclose_maybe_open(span, indented, true)
    }
L
ljedrz 已提交
218

N
Nick Cameron 已提交
219
    pub fn bclose_maybe_open(&mut self,
220
                             span: syntax_pos::Span,
N
Nick Cameron 已提交
221 222 223
                             indented: usize,
                             close_box: bool)
                             -> io::Result<()> {
224
        self.maybe_print_comment(span.hi())?;
J
Jorge Aparicio 已提交
225
        self.break_offset_if_not_bol(1, -(indented as isize))?;
226
        self.s.word("}")?;
227
        if close_box {
J
Jorge Aparicio 已提交
228
            self.end()?; // close the outer-box
229 230 231
        }
        Ok(())
    }
L
ljedrz 已提交
232

233
    pub fn bclose(&mut self, span: syntax_pos::Span) -> io::Result<()> {
234 235 236 237 238 239
        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 已提交
240
            None => false,
241 242
        }
    }
L
ljedrz 已提交
243

244
    pub fn space_if_not_bol(&mut self) -> io::Result<()> {
N
Nick Cameron 已提交
245
        if !self.is_bol() {
246
            self.s.space()?;
N
Nick Cameron 已提交
247
        }
248 249
        Ok(())
    }
L
ljedrz 已提交
250

N
Nick Cameron 已提交
251
    pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> {
252
        if !self.is_bol() {
253
            self.s.break_offset(n, off)
254 255 256 257 258
        } 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.
259
                self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off));
260 261 262 263 264 265 266 267
            }
            Ok(())
        }
    }

    // Synthesizes a comment that was not textually present in the original source
    // file.
    pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
268 269
        self.s.word("/*")?;
        self.s.space()?;
270
        self.s.word(text)?;
271 272
        self.s.space()?;
        self.s.word("*/")
273 274 275 276 277 278
    }

    pub fn commasep_cmnt<T, F, G>(&mut self,
                                  b: Breaks,
                                  elts: &[T],
                                  mut op: F,
N
Nick Cameron 已提交
279 280
                                  mut get_span: G)
                                  -> io::Result<()>
281
        where F: FnMut(&mut State<'_>, &T) -> io::Result<()>,
282
              G: FnMut(&T) -> syntax_pos::Span
283
    {
J
Jorge Aparicio 已提交
284
        self.rbox(0, b)?;
285 286 287
        let len = elts.len();
        let mut i = 0;
        for elt in elts {
288
            self.maybe_print_comment(get_span(elt).hi())?;
J
Jorge Aparicio 已提交
289
            op(self, elt)?;
290 291
            i += 1;
            if i < len {
292
                self.s.word(",")?;
293
                self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi()))?;
J
Jorge Aparicio 已提交
294
                self.space_if_not_bol()?;
295 296 297 298 299
            }
        }
        self.end()
    }

300
    pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr]) -> io::Result<()> {
301
        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
302 303
    }

N
Nick Cameron 已提交
304
    pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
J
Jorge Aparicio 已提交
305
        self.print_inner_attributes(attrs)?;
306
        for &item_id in &_mod.item_ids {
307
            self.ann.nested(self, Nested::Item(item_id))?;
308 309 310 311
        }
        Ok(())
    }

N
Nick Cameron 已提交
312 313 314 315
    pub fn print_foreign_mod(&mut self,
                             nmod: &hir::ForeignMod,
                             attrs: &[ast::Attribute])
                             -> io::Result<()> {
J
Jorge Aparicio 已提交
316
        self.print_inner_attributes(attrs)?;
317
        for item in &nmod.items {
J
Jorge Aparicio 已提交
318
            self.print_foreign_item(item)?;
319 320 321 322
        }
        Ok(())
    }

323 324 325
    pub fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
        if !lifetime.is_elided() {
            self.print_lifetime(lifetime)?;
J
Jorge Aparicio 已提交
326
            self.nbsp()?;
327 328 329 330 331
        }
        Ok(())
    }

    pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
332
        self.maybe_print_comment(ty.span.lo())?;
J
Jorge Aparicio 已提交
333
        self.ibox(0)?;
334
        match ty.node {
C
TyKind  
csmoe 已提交
335
            hir::TyKind::Slice(ref ty) => {
336
                self.s.word("[")?;
J
Jorge Aparicio 已提交
337
                self.print_type(&ty)?;
338
                self.s.word("]")?;
339
            }
C
TyKind  
csmoe 已提交
340
            hir::TyKind::Ptr(ref mt) => {
341
                self.s.word("*")?;
342
                match mt.mutbl {
J
Jorge Aparicio 已提交
343 344
                    hir::MutMutable => self.word_nbsp("mut")?,
                    hir::MutImmutable => self.word_nbsp("const")?,
345
                }
J
Jorge Aparicio 已提交
346
                self.print_type(&mt.ty)?;
347
            }
C
TyKind  
csmoe 已提交
348
            hir::TyKind::Rptr(ref lifetime, ref mt) => {
349
                self.s.word("&")?;
J
Jorge Aparicio 已提交
350 351
                self.print_opt_lifetime(lifetime)?;
                self.print_mt(mt)?;
352
            }
C
TyKind  
csmoe 已提交
353
            hir::TyKind::Never => {
354
                self.s.word("!")?;
355
            },
C
TyKind  
csmoe 已提交
356
            hir::TyKind::Tup(ref elts) => {
J
Jorge Aparicio 已提交
357 358
                self.popen()?;
                self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty))?;
359
                if elts.len() == 1 {
360
                    self.s.word(",")?;
361
                }
J
Jorge Aparicio 已提交
362
                self.pclose()?;
363
            }
C
TyKind  
csmoe 已提交
364
            hir::TyKind::BareFn(ref f) => {
365
                self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &f.generic_params,
366
                                 &f.arg_names[..])?;
367
            }
368
            hir::TyKind::Def(..) => {},
C
TyKind  
csmoe 已提交
369
            hir::TyKind::Path(ref qpath) => {
370
                self.print_qpath(qpath, false)?
371
            }
C
TyKind  
csmoe 已提交
372
            hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
373 374 375 376 377
                let mut first = true;
                for bound in bounds {
                    if first {
                        first = false;
                    } else {
378
                        self.nbsp()?;
379 380 381 382 383
                        self.word_space("+")?;
                    }
                    self.print_poly_trait_ref(bound)?;
                }
                if !lifetime.is_elided() {
384
                    self.nbsp()?;
385 386 387
                    self.word_space("+")?;
                    self.print_lifetime(lifetime)?;
                }
388
            }
C
TyKind  
csmoe 已提交
389
            hir::TyKind::Array(ref ty, ref length) => {
390
                self.s.word("[")?;
J
Jorge Aparicio 已提交
391
                self.print_type(&ty)?;
392
                self.s.word("; ")?;
393
                self.print_anon_const(length)?;
394
                self.s.word("]")?;
395
            }
C
TyKind  
csmoe 已提交
396
            hir::TyKind::Typeof(ref e) => {
397
                self.s.word("typeof(")?;
398
                self.print_anon_const(e)?;
399
                self.s.word(")")?;
400
            }
C
TyKind  
csmoe 已提交
401
            hir::TyKind::Infer => {
402
                self.s.word("_")?;
403
            }
C
TyKind  
csmoe 已提交
404
            hir::TyKind::Err => {
405 406 407
                self.popen()?;
                self.s.word("/*ERROR*/")?;
                self.pclose()?;
408
            }
409 410 411
            hir::TyKind::CVarArgs(_) => {
                self.s.word("...")?;
            }
412 413 414 415
        }
        self.end()
    }

N
Nick Cameron 已提交
416
    pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()> {
J
Jorge Aparicio 已提交
417
        self.hardbreak_if_not_bol()?;
418
        self.maybe_print_comment(item.span.lo())?;
J
Jorge Aparicio 已提交
419
        self.print_outer_attributes(&item.attrs)?;
420
        match item.node {
C
csmoe 已提交
421
            hir::ForeignItemKind::Fn(ref decl, ref arg_names, ref generics) => {
J
Jorge Aparicio 已提交
422 423
                self.head("")?;
                self.print_fn(decl,
424 425 426 427 428 429
                              hir::FnHeader {
                                  unsafety: hir::Unsafety::Normal,
                                  constness: hir::Constness::NotConst,
                                  abi: Abi::Rust,
                                  asyncness: hir::IsAsync::NotAsync,
                              },
430
                              Some(item.ident.name),
J
Jorge Aparicio 已提交
431
                              generics,
432 433 434
                              &item.vis,
                              arg_names,
                              None)?;
J
Jorge Aparicio 已提交
435
                self.end()?; // end head-ibox
436
                self.s.word(";")?;
437 438
                self.end() // end the outer fn box
            }
C
csmoe 已提交
439
            hir::ForeignItemKind::Static(ref t, m) => {
440
                self.head(visibility_qualified(&item.vis, "static"))?;
441
                if m == hir::MutMutable {
J
Jorge Aparicio 已提交
442
                    self.word_space("mut")?;
443
                }
444
                self.print_ident(item.ident)?;
J
Jorge Aparicio 已提交
445 446
                self.word_space(":")?;
                self.print_type(&t)?;
447
                self.s.word(";")?;
J
Jorge Aparicio 已提交
448
                self.end()?; // end the head-ibox
P
Paul Lietar 已提交
449 450
                self.end() // end the outer cbox
            }
C
csmoe 已提交
451
            hir::ForeignItemKind::Type => {
452
                self.head(visibility_qualified(&item.vis, "type"))?;
453
                self.print_ident(item.ident)?;
P
Paul Lietar 已提交
454 455
                self.s.word(";")?;
                self.end()?; // end the head-ibox
456 457 458 459 460 461
                self.end() // end the outer cbox
            }
        }
    }

    fn print_associated_const(&mut self,
462
                              ident: ast::Ident,
463
                              ty: &hir::Ty,
464
                              default: Option<hir::BodyId>,
465
                              vis: &hir::Visibility)
N
Nick Cameron 已提交
466
                              -> io::Result<()> {
467
        self.s.word(visibility_qualified(vis, ""))?;
J
Jorge Aparicio 已提交
468
        self.word_space("const")?;
469
        self.print_ident(ident)?;
J
Jorge Aparicio 已提交
470 471
        self.word_space(":")?;
        self.print_type(ty)?;
472
        if let Some(expr) = default {
473
            self.s.space()?;
J
Jorge Aparicio 已提交
474
            self.word_space("=")?;
475
            self.ann.nested(self, Nested::Body(expr))?;
476
        }
477
        self.s.word(";")
478 479 480
    }

    fn print_associated_type(&mut self,
481
                             ident: ast::Ident,
V
varkor 已提交
482
                             bounds: Option<&hir::GenericBounds>,
483 484
                             ty: Option<&hir::Ty>)
                             -> io::Result<()> {
J
Jorge Aparicio 已提交
485
        self.word_space("type")?;
486
        self.print_ident(ident)?;
487
        if let Some(bounds) = bounds {
J
Jorge Aparicio 已提交
488
            self.print_bounds(":", bounds)?;
489 490
        }
        if let Some(ty) = ty {
491
            self.s.space()?;
J
Jorge Aparicio 已提交
492 493
            self.word_space("=")?;
            self.print_type(ty)?;
494
        }
495
        self.s.word(";")
496 497 498 499
    }

    /// Pretty-print an item
    pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
J
Jorge Aparicio 已提交
500
        self.hardbreak_if_not_bol()?;
501
        self.maybe_print_comment(item.span.lo())?;
J
Jorge Aparicio 已提交
502
        self.print_outer_attributes(&item.attrs)?;
V
varkor 已提交
503
        self.ann.pre(self, AnnNode::Item(item))?;
504
        match item.node {
C
csmoe 已提交
505
            hir::ItemKind::ExternCrate(orig_name) => {
506
                self.head(visibility_qualified(&item.vis, "extern crate"))?;
507 508
                if let Some(orig_name) = orig_name {
                    self.print_name(orig_name)?;
509 510 511
                    self.s.space()?;
                    self.s.word("as")?;
                    self.s.space()?;
512
                }
513
                self.print_ident(item.ident)?;
514
                self.s.word(";")?;
J
Jorge Aparicio 已提交
515 516
                self.end()?; // end inner head-block
                self.end()?; // end outer head-block
517
            }
C
csmoe 已提交
518
            hir::ItemKind::Use(ref path, kind) => {
519
                self.head(visibility_qualified(&item.vis, "use"))?;
520 521 522 523
                self.print_path(path, false)?;

                match kind {
                    hir::UseKind::Single => {
524
                        if path.segments.last().unwrap().ident != item.ident {
525
                            self.s.space()?;
526
                            self.word_space("as")?;
527
                            self.print_ident(item.ident)?;
528
                        }
529
                        self.s.word(";")?;
530
                    }
531 532
                    hir::UseKind::Glob => self.s.word("::*;")?,
                    hir::UseKind::ListStem => self.s.word("::{};")?
533
                }
J
Jorge Aparicio 已提交
534 535
                self.end()?; // end inner head-block
                self.end()?; // end outer head-block
536
            }
C
csmoe 已提交
537
            hir::ItemKind::Static(ref ty, m, expr) => {
538
                self.head(visibility_qualified(&item.vis, "static"))?;
539
                if m == hir::MutMutable {
J
Jorge Aparicio 已提交
540
                    self.word_space("mut")?;
541
                }
542
                self.print_ident(item.ident)?;
J
Jorge Aparicio 已提交
543 544
                self.word_space(":")?;
                self.print_type(&ty)?;
545
                self.s.space()?;
J
Jorge Aparicio 已提交
546
                self.end()?; // end the head-ibox
547

J
Jorge Aparicio 已提交
548
                self.word_space("=")?;
549
                self.ann.nested(self, Nested::Body(expr))?;
550
                self.s.word(";")?;
J
Jorge Aparicio 已提交
551
                self.end()?; // end the outer cbox
552
            }
C
csmoe 已提交
553
            hir::ItemKind::Const(ref ty, expr) => {
554
                self.head(visibility_qualified(&item.vis, "const"))?;
555
                self.print_ident(item.ident)?;
J
Jorge Aparicio 已提交
556 557
                self.word_space(":")?;
                self.print_type(&ty)?;
558
                self.s.space()?;
J
Jorge Aparicio 已提交
559 560 561
                self.end()?; // end the head-ibox

                self.word_space("=")?;
562
                self.ann.nested(self, Nested::Body(expr))?;
563
                self.s.word(";")?;
J
Jorge Aparicio 已提交
564
                self.end()?; // end the outer cbox
565
            }
V
varkor 已提交
566
            hir::ItemKind::Fn(ref decl, header, ref param_names, body) => {
J
Jorge Aparicio 已提交
567 568
                self.head("")?;
                self.print_fn(decl,
W
Without Boats 已提交
569
                              header,
570
                              Some(item.ident.name),
V
varkor 已提交
571
                              param_names,
572 573 574
                              &item.vis,
                              &[],
                              Some(body))?;
575
                self.s.word(" ")?;
576 577
                self.end()?; // need to close a box
                self.end()?; // need to close a box
578
                self.ann.nested(self, Nested::Body(body))?;
579
            }
C
csmoe 已提交
580
            hir::ItemKind::Mod(ref _mod) => {
581
                self.head(visibility_qualified(&item.vis, "mod"))?;
582
                self.print_ident(item.ident)?;
J
Jorge Aparicio 已提交
583 584 585 586
                self.nbsp()?;
                self.bopen()?;
                self.print_mod(_mod, &item.attrs)?;
                self.bclose(item.span)?;
587
            }
C
csmoe 已提交
588
            hir::ItemKind::ForeignMod(ref nmod) => {
J
Jorge Aparicio 已提交
589
                self.head("extern")?;
590
                self.word_nbsp(nmod.abi.to_string())?;
J
Jorge Aparicio 已提交
591 592 593
                self.bopen()?;
                self.print_foreign_mod(nmod, &item.attrs)?;
                self.bclose(item.span)?;
594
            }
C
csmoe 已提交
595
            hir::ItemKind::GlobalAsm(ref ga) => {
596
                self.head(visibility_qualified(&item.vis, "global asm"))?;
597
                self.s.word(ga.asm.as_str().to_string())?;
598 599
                self.end()?
            }
C
csmoe 已提交
600
            hir::ItemKind::Ty(ref ty, ref generics) => {
601
                self.head(visibility_qualified(&item.vis, "type"))?;
602
                self.print_ident(item.ident)?;
603
                self.print_generic_params(&generics.params)?;
J
Jorge Aparicio 已提交
604 605
                self.end()?; // end the inner ibox

606
                self.print_where_clause(&generics.where_clause)?;
607
                self.s.space()?;
J
Jorge Aparicio 已提交
608 609
                self.word_space("=")?;
                self.print_type(&ty)?;
610
                self.s.word(";")?;
J
Jorge Aparicio 已提交
611
                self.end()?; // end the outer ibox
612
            }
C
csmoe 已提交
613
            hir::ItemKind::Existential(ref exist) => {
614
                self.head(visibility_qualified(&item.vis, "existential type"))?;
615
                self.print_ident(item.ident)?;
616 617 618 619 620 621 622
                self.print_generic_params(&exist.generics.params)?;
                self.end()?; // end the inner ibox

                self.print_where_clause(&exist.generics.where_clause)?;
                self.s.space()?;
                let mut real_bounds = Vec::with_capacity(exist.bounds.len());
                for b in exist.bounds.iter() {
623
                    if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
624 625 626 627 628 629 630 631 632 633 634
                        self.s.space()?;
                        self.word_space("for ?")?;
                        self.print_trait_ref(&ptr.trait_ref)?;
                    } else {
                        real_bounds.push(b.clone());
                    }
                }
                self.print_bounds(":", &real_bounds[..])?;
                self.s.word(";")?;
                self.end()?; // end the outer ibox
            }
C
csmoe 已提交
635
            hir::ItemKind::Enum(ref enum_definition, ref params) => {
636 637
                self.print_enum_def(enum_definition, params, item.ident.name, item.span,
                                    &item.vis)?;
638
            }
C
csmoe 已提交
639
            hir::ItemKind::Struct(ref struct_def, ref generics) => {
640
                self.head(visibility_qualified(&item.vis, "struct"))?;
641
                self.print_struct(struct_def, generics, item.ident.name, item.span, true)?;
642
            }
C
csmoe 已提交
643
            hir::ItemKind::Union(ref struct_def, ref generics) => {
644
                self.head(visibility_qualified(&item.vis, "union"))?;
645
                self.print_struct(struct_def, generics, item.ident.name, item.span, true)?;
V
Vadim Petrochenkov 已提交
646
            }
C
csmoe 已提交
647
            hir::ItemKind::Impl(unsafety,
648
                          polarity,
649
                          defaultness,
650 651 652 653
                          ref generics,
                          ref opt_trait,
                          ref ty,
                          ref impl_items) => {
J
Jorge Aparicio 已提交
654
                self.head("")?;
655
                self.print_visibility(&item.vis)?;
656
                self.print_defaultness(defaultness)?;
J
Jorge Aparicio 已提交
657 658
                self.print_unsafety(unsafety)?;
                self.word_nbsp("impl")?;
659

660 661
                if !generics.params.is_empty() {
                    self.print_generic_params(&generics.params)?;
662
                    self.s.space()?;
663 664
                }

L
ljedrz 已提交
665 666
                if let hir::ImplPolarity::Negative = polarity {
                    self.s.word("!")?;
667 668
                }

L
ljedrz 已提交
669 670 671 672
                if let Some(ref t) = opt_trait {
                    self.print_trait_ref(t)?;
                    self.s.space()?;
                    self.word_space("for")?;
673 674
                }

J
Jorge Aparicio 已提交
675 676
                self.print_type(&ty)?;
                self.print_where_clause(&generics.where_clause)?;
677

678
                self.s.space()?;
J
Jorge Aparicio 已提交
679 680
                self.bopen()?;
                self.print_inner_attributes(&item.attrs)?;
681
                for impl_item in impl_items {
682
                    self.ann.nested(self, Nested::ImplItem(impl_item.id))?;
683
                }
J
Jorge Aparicio 已提交
684
                self.bclose(item.span)?;
685
            }
C
csmoe 已提交
686
            hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref trait_items) => {
J
Jorge Aparicio 已提交
687
                self.head("")?;
688
                self.print_visibility(&item.vis)?;
689
                self.print_is_auto(is_auto)?;
J
Jorge Aparicio 已提交
690 691
                self.print_unsafety(unsafety)?;
                self.word_nbsp("trait")?;
692
                self.print_ident(item.ident)?;
693
                self.print_generic_params(&generics.params)?;
694 695
                let mut real_bounds = Vec::with_capacity(bounds.len());
                for b in bounds.iter() {
V
varkor 已提交
696
                    if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
697
                        self.s.space()?;
J
Jorge Aparicio 已提交
698 699
                        self.word_space("for ?")?;
                        self.print_trait_ref(&ptr.trait_ref)?;
700 701 702 703
                    } else {
                        real_bounds.push(b.clone());
                    }
                }
J
Jorge Aparicio 已提交
704 705
                self.print_bounds(":", &real_bounds[..])?;
                self.print_where_clause(&generics.where_clause)?;
706
                self.s.word(" ")?;
J
Jorge Aparicio 已提交
707
                self.bopen()?;
708
                for trait_item in trait_items {
709
                    self.ann.nested(self, Nested::TraitItem(trait_item.id))?;
710
                }
J
Jorge Aparicio 已提交
711
                self.bclose(item.span)?;
712
            }
C
csmoe 已提交
713
            hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
A
Alex Burka 已提交
714 715 716
                self.head("")?;
                self.print_visibility(&item.vis)?;
                self.word_nbsp("trait")?;
717
                self.print_ident(item.ident)?;
718
                self.print_generic_params(&generics.params)?;
A
Alex Burka 已提交
719 720 721
                let mut real_bounds = Vec::with_capacity(bounds.len());
                // FIXME(durka) this seems to be some quite outdated syntax
                for b in bounds.iter() {
V
varkor 已提交
722
                    if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
A
Alex Burka 已提交
723 724 725 726 727 728 729
                        self.s.space()?;
                        self.word_space("for ?")?;
                        self.print_trait_ref(&ptr.trait_ref)?;
                    } else {
                        real_bounds.push(b.clone());
                    }
                }
730 731
                self.nbsp()?;
                self.print_bounds("=", &real_bounds[..])?;
A
Alex Burka 已提交
732 733 734
                self.print_where_clause(&generics.where_clause)?;
                self.s.word(";")?;
            }
735
        }
V
varkor 已提交
736
        self.ann.post(self, AnnNode::Item(item))
737 738
    }

739
    pub fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
740
        self.print_path(&t.path, false)
741 742
    }

743 744 745 746 747 748 749
    fn print_formal_generic_params(
        &mut self,
        generic_params: &[hir::GenericParam]
    ) -> io::Result<()> {
        if !generic_params.is_empty() {
            self.s.word("for")?;
            self.print_generic_params(generic_params)?;
750
            self.nbsp()?;
751 752 753 754 755
        }
        Ok(())
    }

    fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> {
756
        self.print_formal_generic_params(&t.bound_generic_params)?;
757 758 759
        self.print_trait_ref(&t.trait_ref)
    }

N
Nick Cameron 已提交
760 761 762 763
    pub fn print_enum_def(&mut self,
                          enum_definition: &hir::EnumDef,
                          generics: &hir::Generics,
                          name: ast::Name,
764
                          span: syntax_pos::Span,
765
                          visibility: &hir::Visibility)
N
Nick Cameron 已提交
766
                          -> io::Result<()> {
767
        self.head(visibility_qualified(visibility, "enum"))?;
J
Jorge Aparicio 已提交
768
        self.print_name(name)?;
769
        self.print_generic_params(&generics.params)?;
J
Jorge Aparicio 已提交
770
        self.print_where_clause(&generics.where_clause)?;
771
        self.s.space()?;
772 773 774 775
        self.print_variants(&enum_definition.variants, span)
    }

    pub fn print_variants(&mut self,
776
                          variants: &[hir::Variant],
777
                          span: syntax_pos::Span)
N
Nick Cameron 已提交
778
                          -> io::Result<()> {
J
Jorge Aparicio 已提交
779
        self.bopen()?;
780
        for v in variants {
J
Jorge Aparicio 已提交
781
            self.space_if_not_bol()?;
782
            self.maybe_print_comment(v.span.lo())?;
J
Jorge Aparicio 已提交
783 784 785
            self.print_outer_attributes(&v.node.attrs)?;
            self.ibox(indent_unit)?;
            self.print_variant(v)?;
786
            self.s.word(",")?;
J
Jorge Aparicio 已提交
787 788
            self.end()?;
            self.maybe_print_trailing_comment(v.span, None)?;
789 790 791 792
        }
        self.bclose(span)
    }

793
    pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
794
        match vis.node {
795 796 797 798
            hir::VisibilityKind::Public => self.word_nbsp("pub")?,
            hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate")?,
            hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)")?,
            hir::VisibilityKind::Restricted { ref path, .. } => {
799
                self.s.word("pub(")?;
800
                if path.segments.len() == 1 &&
801
                   path.segments[0].ident.name == kw::Super {
802 803 804 805 806 807 808 809
                    // Special case: `super` can print like `pub(super)`.
                    self.s.word("super")?;
                } else {
                    // Everything else requires `in` at present.
                    self.word_nbsp("in")?;
                    self.print_path(path, false)?;
                }
                self.word_nbsp(")")?;
810
            }
811
            hir::VisibilityKind::Inherited => ()
812
        }
813 814

        Ok(())
815 816
    }

817
    pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {
818 819 820
        match defaultness {
            hir::Defaultness::Default { .. } => self.word_nbsp("default")?,
            hir::Defaultness::Final => (),
821 822 823 824
        }
        Ok(())
    }

825
    pub fn print_struct(&mut self,
826
                        struct_def: &hir::VariantData,
827
                        generics: &hir::Generics,
V
Vadim Petrochenkov 已提交
828
                        name: ast::Name,
829
                        span: syntax_pos::Span,
830
                        print_finalizer: bool)
N
Nick Cameron 已提交
831
                        -> io::Result<()> {
J
Jorge Aparicio 已提交
832
        self.print_name(name)?;
833
        self.print_generic_params(&generics.params)?;
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
        match struct_def {
            hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => {
                if let hir::VariantData::Tuple(..) = struct_def {
                    self.popen()?;
                    self.commasep(Inconsistent, struct_def.fields(), |s, field| {
                        s.maybe_print_comment(field.span.lo())?;
                        s.print_outer_attributes(&field.attrs)?;
                        s.print_visibility(&field.vis)?;
                        s.print_type(&field.ty)
                    })?;
                    self.pclose()?;
                }
                self.print_where_clause(&generics.where_clause)?;
                if print_finalizer {
                    self.s.word(";")?;
                }
                self.end()?;
                self.end() // close the outer-box
852
            }
853 854 855 856
            hir::VariantData::Struct(..) => {
                self.print_where_clause(&generics.where_clause)?;
                self.nbsp()?;
                self.bopen()?;
J
Jorge Aparicio 已提交
857
                self.hardbreak_if_not_bol()?;
858

859 860 861 862 863 864 865 866 867 868 869 870 871
                for field in struct_def.fields() {
                    self.hardbreak_if_not_bol()?;
                    self.maybe_print_comment(field.span.lo())?;
                    self.print_outer_attributes(&field.attrs)?;
                    self.print_visibility(&field.vis)?;
                    self.print_ident(field.ident)?;
                    self.word_nbsp(":")?;
                    self.print_type(&field.ty)?;
                    self.s.word(",")?;
                }

                self.bclose(span)
            }
872 873 874 875
        }
    }

    pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
J
Jorge Aparicio 已提交
876
        self.head("")?;
877
        let generics = hir::Generics::empty();
878
        self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false)?;
879
        if let Some(ref d) = v.node.disr_expr {
880
            self.s.space()?;
881
            self.word_space("=")?;
882
            self.print_anon_const(d)?;
883
        }
884
        Ok(())
885 886
    }
    pub fn print_method_sig(&mut self,
887
                            ident: ast::Ident,
888
                            m: &hir::MethodSig,
889
                            generics: &hir::Generics,
890
                            vis: &hir::Visibility,
891
                            arg_names: &[ast::Ident],
892
                            body_id: Option<hir::BodyId>)
893 894
                            -> io::Result<()> {
        self.print_fn(&m.decl,
W
Without Boats 已提交
895
                      m.header,
896
                      Some(ident.name),
897
                      generics,
898 899 900
                      vis,
                      arg_names,
                      body_id)
901 902
    }

N
Nick Cameron 已提交
903
    pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
L
ljedrz 已提交
904
        self.ann.pre(self, AnnNode::SubItem(ti.hir_id))?;
J
Jorge Aparicio 已提交
905
        self.hardbreak_if_not_bol()?;
906
        self.maybe_print_comment(ti.span.lo())?;
J
Jorge Aparicio 已提交
907
        self.print_outer_attributes(&ti.attrs)?;
908
        match ti.node {
909
            hir::TraitItemKind::Const(ref ty, default) => {
910 911
                let vis = Spanned { span: syntax_pos::DUMMY_SP,
                                    node: hir::VisibilityKind::Inherited };
912
                self.print_associated_const(ti.ident, &ty, default, &vis)?;
913
            }
914
            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => {
915 916
                let vis = Spanned { span: syntax_pos::DUMMY_SP,
                                    node: hir::VisibilityKind::Inherited };
917
                self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None)?;
918
                self.s.word(";")?;
919 920
            }
            hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
921 922
                let vis = Spanned { span: syntax_pos::DUMMY_SP,
                                    node: hir::VisibilityKind::Inherited };
923
                self.head("")?;
924
                self.print_method_sig(ti.ident, sig, &ti.generics, &vis, &[], Some(body))?;
925 926 927
                self.nbsp()?;
                self.end()?; // need to close a box
                self.end()?; // need to close a box
928
                self.ann.nested(self, Nested::Body(body))?;
929
            }
930
            hir::TraitItemKind::Type(ref bounds, ref default) => {
931
                self.print_associated_type(ti.ident,
J
Jorge Aparicio 已提交
932 933
                                           Some(bounds),
                                           default.as_ref().map(|ty| &**ty))?;
934 935
            }
        }
L
ljedrz 已提交
936
        self.ann.post(self, AnnNode::SubItem(ti.hir_id))
937 938 939
    }

    pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
L
ljedrz 已提交
940
        self.ann.pre(self, AnnNode::SubItem(ii.hir_id))?;
J
Jorge Aparicio 已提交
941
        self.hardbreak_if_not_bol()?;
942
        self.maybe_print_comment(ii.span.lo())?;
J
Jorge Aparicio 已提交
943
        self.print_outer_attributes(&ii.attrs)?;
944
        self.print_defaultness(ii.defaultness)?;
945

946
        match ii.node {
947
            hir::ImplItemKind::Const(ref ty, expr) => {
948
                self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis)?;
949
            }
950
            hir::ImplItemKind::Method(ref sig, body) => {
J
Jorge Aparicio 已提交
951
                self.head("")?;
952
                self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body))?;
J
Jorge Aparicio 已提交
953
                self.nbsp()?;
954 955
                self.end()?; // need to close a box
                self.end()?; // need to close a box
956
                self.ann.nested(self, Nested::Body(body))?;
957
            }
958
            hir::ImplItemKind::Type(ref ty) => {
959
                self.print_associated_type(ii.ident, None, Some(ty))?;
960
            }
O
Oliver Schneider 已提交
961 962 963 964
            hir::ImplItemKind::Existential(ref bounds) => {
                self.word_space("existential")?;
                self.print_associated_type(ii.ident, Some(bounds), None)?;
            }
965
        }
L
ljedrz 已提交
966
        self.ann.post(self, AnnNode::SubItem(ii.hir_id))
967 968
    }

969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
    pub fn print_local(
        &mut self,
        init: Option<&hir::Expr>,
        decl: impl Fn(&mut Self) -> io::Result<()>
    ) -> io::Result<()> {
        self.space_if_not_bol()?;
        self.ibox(indent_unit)?;
        self.word_nbsp("let")?;

        self.ibox(indent_unit)?;
        decl(self)?;
        self.end()?;

        if let Some(ref init) = init {
            self.nbsp()?;
            self.word_space("=")?;
            self.print_expr(&init)?;
        }
        self.end()
    }

990
    pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
991
        self.maybe_print_comment(st.span.lo())?;
992
        match st.node {
993
            hir::StmtKind::Local(ref loc) => {
994
                self.print_local(loc.init.deref(), |this| this.print_local_decl(&loc))?;
995
            }
996 997
            hir::StmtKind::Item(item) => {
                self.ann.nested(self, Nested::Item(item))?
998
            }
999
            hir::StmtKind::Expr(ref expr) => {
J
Jorge Aparicio 已提交
1000 1001
                self.space_if_not_bol()?;
                self.print_expr(&expr)?;
1002
            }
1003
            hir::StmtKind::Semi(ref expr) => {
J
Jorge Aparicio 已提交
1004 1005
                self.space_if_not_bol()?;
                self.print_expr(&expr)?;
1006
                self.s.word(";")?;
1007 1008 1009
            }
        }
        if stmt_ends_with_semi(&st.node) {
1010
            self.s.word(";")?;
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
        }
        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 已提交
1023 1024 1025 1026
    pub fn print_block_unclosed_indent(&mut self,
                                       blk: &hir::Block,
                                       indented: usize)
                                       -> io::Result<()> {
1027 1028 1029 1030 1031
        self.print_block_maybe_unclosed(blk, indented, &[], false)
    }

    pub fn print_block_with_attrs(&mut self,
                                  blk: &hir::Block,
N
Nick Cameron 已提交
1032 1033
                                  attrs: &[ast::Attribute])
                                  -> io::Result<()> {
1034 1035 1036 1037 1038 1039
        self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
    }

    pub fn print_block_maybe_unclosed(&mut self,
                                      blk: &hir::Block,
                                      indented: usize,
1040
                                      attrs: &[ast::Attribute],
N
Nick Cameron 已提交
1041 1042
                                      close_box: bool)
                                      -> io::Result<()> {
1043
        match blk.rules {
J
Jorge Aparicio 已提交
1044 1045 1046
            hir::UnsafeBlock(..) => self.word_space("unsafe")?,
            hir::PushUnsafeBlock(..) => self.word_space("push_unsafe")?,
            hir::PopUnsafeBlock(..) => self.word_space("pop_unsafe")?,
N
Nick Cameron 已提交
1047
            hir::DefaultBlock => (),
1048
        }
1049
        self.maybe_print_comment(blk.span.lo())?;
V
varkor 已提交
1050
        self.ann.pre(self, AnnNode::Block(blk))?;
J
Jorge Aparicio 已提交
1051
        self.bopen()?;
1052

J
Jorge Aparicio 已提交
1053
        self.print_inner_attributes(attrs)?;
1054 1055

        for st in &blk.stmts {
J
Jorge Aparicio 已提交
1056
            self.print_stmt(st)?;
1057
        }
L
ljedrz 已提交
1058 1059 1060 1061
        if let Some(ref expr) = blk.expr {
            self.space_if_not_bol()?;
            self.print_expr(&expr)?;
            self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()))?;
1062
        }
J
Jorge Aparicio 已提交
1063
        self.bclose_maybe_open(blk.span, indented, close_box)?;
V
varkor 已提交
1064
        self.ann.post(self, AnnNode::Block(blk))
1065 1066
    }

1067 1068 1069
    pub fn print_anon_const(&mut self, constant: &hir::AnonConst) -> io::Result<()> {
        self.ann.nested(self, Nested::Body(constant.body))
    }
1070

1071
    fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> {
J
Jorge Aparicio 已提交
1072 1073
        self.popen()?;
        self.commasep_exprs(Inconsistent, args)?;
1074 1075 1076
        self.pclose()
    }

1077
    pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr, prec: i8) -> io::Result<()> {
1078
        let needs_par = expr.precedence().order() < prec;
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
        if needs_par {
            self.popen()?;
        }
        self.print_expr(expr)?;
        if needs_par {
            self.pclose()?;
        }
        Ok(())
    }

    /// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
    /// `if cond { ... }`.
    pub fn print_expr_as_cond(&mut self, expr: &hir::Expr) -> io::Result<()> {
        let needs_par = match expr.node {
            // These cases need parens due to the parse error observed in #26461: `if return {}`
            // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
C
csmoe 已提交
1095 1096 1097
            hir::ExprKind::Closure(..) |
            hir::ExprKind::Ret(..) |
            hir::ExprKind::Break(..) => true,
1098 1099 1100 1101

            _ => contains_exterior_struct_lit(expr),
        };

1102
        if needs_par {
J
Jorge Aparicio 已提交
1103
            self.popen()?;
1104
        }
J
Jorge Aparicio 已提交
1105
        self.print_expr(expr)?;
1106
        if needs_par {
J
Jorge Aparicio 已提交
1107
            self.pclose()?;
1108 1109 1110 1111
        }
        Ok(())
    }

1112
    fn print_expr_vec(&mut self, exprs: &[hir::Expr]) -> io::Result<()> {
J
Jorge Aparicio 已提交
1113
        self.ibox(indent_unit)?;
1114
        self.s.word("[")?;
1115
        self.commasep_exprs(Inconsistent, exprs)?;
1116
        self.s.word("]")?;
1117 1118 1119
        self.end()
    }

1120
    fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::AnonConst) -> io::Result<()> {
J
Jorge Aparicio 已提交
1121
        self.ibox(indent_unit)?;
1122
        self.s.word("[")?;
J
Jorge Aparicio 已提交
1123 1124
        self.print_expr(element)?;
        self.word_space(";")?;
1125
        self.print_anon_const(count)?;
1126
        self.s.word("]")?;
1127 1128 1129 1130
        self.end()
    }

    fn print_expr_struct(&mut self,
1131
                         qpath: &hir::QPath,
1132
                         fields: &[hir::Field],
N
Nick Cameron 已提交
1133 1134
                         wth: &Option<P<hir::Expr>>)
                         -> io::Result<()> {
1135
        self.print_qpath(qpath, true)?;
1136
        self.s.word("{")?;
J
Jorge Aparicio 已提交
1137
        self.commasep_cmnt(Consistent,
J
Jorge Aparicio 已提交
1138 1139 1140
                           &fields[..],
                           |s, field| {
                               s.ibox(indent_unit)?;
1141
                               if !field.is_shorthand {
1142
                                    s.print_ident(field.ident)?;
1143 1144
                                    s.word_space(":")?;
                               }
J
Jorge Aparicio 已提交
1145 1146 1147 1148
                               s.print_expr(&field.expr)?;
                               s.end()
                           },
                           |f| f.span)?;
1149 1150
        match *wth {
            Some(ref expr) => {
J
Jorge Aparicio 已提交
1151
                self.ibox(indent_unit)?;
1152
                if !fields.is_empty() {
1153 1154
                    self.s.word(",")?;
                    self.s.space()?;
1155
                }
1156
                self.s.word("..")?;
J
Jorge Aparicio 已提交
1157 1158
                self.print_expr(&expr)?;
                self.end()?;
1159 1160
            }
            _ => if !fields.is_empty() {
1161
                self.s.word(",")?
N
Nick Cameron 已提交
1162
            },
1163
        }
1164
        self.s.word("}")?;
1165 1166 1167
        Ok(())
    }

1168
    fn print_expr_tup(&mut self, exprs: &[hir::Expr]) -> io::Result<()> {
J
Jorge Aparicio 已提交
1169
        self.popen()?;
1170
        self.commasep_exprs(Inconsistent, exprs)?;
1171
        if exprs.len() == 1 {
1172
            self.s.word(",")?;
1173 1174 1175 1176
        }
        self.pclose()
    }

1177
    fn print_expr_call(&mut self, func: &hir::Expr, args: &[hir::Expr]) -> io::Result<()> {
1178 1179
        let prec =
            match func.node {
C
csmoe 已提交
1180
                hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
1181 1182 1183 1184
                _ => parser::PREC_POSTFIX,
            };

        self.print_expr_maybe_paren(func, prec)?;
1185 1186 1187 1188
        self.print_call_post(args)
    }

    fn print_expr_method_call(&mut self,
1189
                              segment: &hir::PathSegment,
1190
                              args: &[hir::Expr])
N
Nick Cameron 已提交
1191
                              -> io::Result<()> {
1192
        let base_args = &args[1..];
1193
        self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?;
1194
        self.s.word(".")?;
1195
        self.print_ident(segment.ident)?;
1196

1197
        segment.with_generic_args(|generic_args| {
1198 1199
            if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() {
                return self.print_generic_args(&generic_args, segment.infer_types, true);
1200
            }
1201
            Ok(())
1202
        })?;
1203 1204 1205 1206 1207 1208
        self.print_call_post(base_args)
    }

    fn print_expr_binary(&mut self,
                         op: hir::BinOp,
                         lhs: &hir::Expr,
N
Nick Cameron 已提交
1209 1210
                         rhs: &hir::Expr)
                         -> io::Result<()> {
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
        let assoc_op = bin_op_to_assoc_op(op.node);
        let prec = assoc_op.precedence() as i8;
        let fixity = assoc_op.fixity();

        let (left_prec, right_prec) = match fixity {
            Fixity::Left => (prec, prec + 1),
            Fixity::Right => (prec + 1, prec),
            Fixity::None => (prec + 1, prec + 1),
        };

1221 1222 1223 1224
        let left_prec = match (&lhs.node, op.node) {
            // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
            // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
            // of `(x as i32) < ...`. We need to convince it _not_ to do that.
C
csmoe 已提交
1225 1226
            (&hir::ExprKind::Cast { .. }, hir::BinOpKind::Lt) |
            (&hir::ExprKind::Cast { .. }, hir::BinOpKind::Shl) => parser::PREC_FORCE_PAREN,
1227 1228 1229
            _ => left_prec,
        };

1230
        self.print_expr_maybe_paren(lhs, left_prec)?;
1231
        self.s.space()?;
1232
        self.word_space(op.node.as_str())?;
1233
        self.print_expr_maybe_paren(rhs, right_prec)
1234 1235
    }

N
Nick Cameron 已提交
1236
    fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> {
1237
        self.s.word(op.as_str())?;
1238
        self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
1239 1240 1241 1242
    }

    fn print_expr_addr_of(&mut self,
                          mutability: hir::Mutability,
N
Nick Cameron 已提交
1243 1244
                          expr: &hir::Expr)
                          -> io::Result<()> {
1245
        self.s.word("&")?;
J
Jorge Aparicio 已提交
1246
        self.print_mutability(mutability)?;
1247
        self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
1248 1249
    }

1250 1251
    fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> {
        self.maybe_print_comment(lit.span.lo())?;
1252
        self.writer().word(pprust::literal_to_string(lit.node.to_lit_token()))
1253 1254
    }

1255
    pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
1256
        self.maybe_print_comment(expr.span.lo())?;
1257
        self.print_outer_attributes(&expr.attrs)?;
J
Jorge Aparicio 已提交
1258
        self.ibox(indent_unit)?;
V
varkor 已提交
1259
        self.ann.pre(self, AnnNode::Expr(expr))?;
1260
        match expr.node {
C
csmoe 已提交
1261
            hir::ExprKind::Box(ref expr) => {
J
Jorge Aparicio 已提交
1262
                self.word_space("box")?;
1263
                self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)?;
1264
            }
C
csmoe 已提交
1265
            hir::ExprKind::Array(ref exprs) => {
1266
                self.print_expr_vec(exprs)?;
1267
            }
C
csmoe 已提交
1268
            hir::ExprKind::Repeat(ref element, ref count) => {
1269
                self.print_expr_repeat(&element, count)?;
1270
            }
C
csmoe 已提交
1271
            hir::ExprKind::Struct(ref qpath, ref fields, ref wth) => {
1272
                self.print_expr_struct(qpath, &fields[..], wth)?;
1273
            }
C
csmoe 已提交
1274
            hir::ExprKind::Tup(ref exprs) => {
1275
                self.print_expr_tup(exprs)?;
1276
            }
C
csmoe 已提交
1277
            hir::ExprKind::Call(ref func, ref args) => {
1278
                self.print_expr_call(&func, args)?;
1279
            }
C
csmoe 已提交
1280
            hir::ExprKind::MethodCall(ref segment, _, ref args) => {
1281
                self.print_expr_method_call(segment, args)?;
1282
            }
C
csmoe 已提交
1283
            hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
J
Jorge Aparicio 已提交
1284
                self.print_expr_binary(op, &lhs, &rhs)?;
1285
            }
C
csmoe 已提交
1286
            hir::ExprKind::Unary(op, ref expr) => {
J
Jorge Aparicio 已提交
1287
                self.print_expr_unary(op, &expr)?;
1288
            }
C
csmoe 已提交
1289
            hir::ExprKind::AddrOf(m, ref expr) => {
J
Jorge Aparicio 已提交
1290
                self.print_expr_addr_of(m, &expr)?;
1291
            }
C
csmoe 已提交
1292
            hir::ExprKind::Lit(ref lit) => {
J
Jorge Aparicio 已提交
1293
                self.print_literal(&lit)?;
1294
            }
C
csmoe 已提交
1295
            hir::ExprKind::Cast(ref expr, ref ty) => {
1296 1297
                let prec = AssocOp::As.precedence() as i8;
                self.print_expr_maybe_paren(&expr, prec)?;
1298
                self.s.space()?;
J
Jorge Aparicio 已提交
1299 1300
                self.word_space("as")?;
                self.print_type(&ty)?;
1301
            }
C
csmoe 已提交
1302
            hir::ExprKind::Type(ref expr, ref ty) => {
1303 1304
                let prec = AssocOp::Colon.precedence() as i8;
                self.print_expr_maybe_paren(&expr, prec)?;
J
Jorge Aparicio 已提交
1305 1306
                self.word_space(":")?;
                self.print_type(&ty)?;
1307
            }
1308
            hir::ExprKind::DropTemps(ref init) => {
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
                // Print `{`:
                self.cbox(indent_unit)?;
                self.ibox(0)?;
                self.bopen()?;

                // Print `let _t = $init;`:
                let temp = ast::Ident::from_str("_t");
                self.print_local(Some(init), |this| this.print_ident(temp))?;
                self.s.word(";")?;

                // Print `_t`:
                self.space_if_not_bol()?;
                self.print_ident(temp)?;

                // Print `}`:
                self.bclose_maybe_open(expr.span, indent_unit, true)?;
            }
C
csmoe 已提交
1326
            hir::ExprKind::While(ref test, ref blk, opt_label) => {
1327
                if let Some(label) = opt_label {
1328
                    self.print_ident(label.ident)?;
J
Jorge Aparicio 已提交
1329
                    self.word_space(":")?;
1330
                }
J
Jorge Aparicio 已提交
1331
                self.head("while")?;
1332
                self.print_expr_as_cond(&test)?;
1333
                self.s.space()?;
J
Jorge Aparicio 已提交
1334
                self.print_block(&blk)?;
1335
            }
C
csmoe 已提交
1336
            hir::ExprKind::Loop(ref blk, opt_label, _) => {
1337
                if let Some(label) = opt_label {
1338
                    self.print_ident(label.ident)?;
J
Jorge Aparicio 已提交
1339
                    self.word_space(":")?;
1340
                }
J
Jorge Aparicio 已提交
1341
                self.head("loop")?;
1342
                self.s.space()?;
J
Jorge Aparicio 已提交
1343
                self.print_block(&blk)?;
1344
            }
C
csmoe 已提交
1345
            hir::ExprKind::Match(ref expr, ref arms, _) => {
J
Jorge Aparicio 已提交
1346 1347 1348
                self.cbox(indent_unit)?;
                self.ibox(4)?;
                self.word_nbsp("match")?;
1349
                self.print_expr_as_cond(&expr)?;
1350
                self.s.space()?;
J
Jorge Aparicio 已提交
1351
                self.bopen()?;
1352
                for arm in arms {
J
Jorge Aparicio 已提交
1353
                    self.print_arm(arm)?;
1354
                }
J
Jorge Aparicio 已提交
1355
                self.bclose_(expr.span, indent_unit)?;
1356
            }
C
csmoe 已提交
1357
            hir::ExprKind::Closure(capture_clause, ref decl, body, _fn_decl_span, _gen) => {
J
Jorge Aparicio 已提交
1358
                self.print_capture_clause(capture_clause)?;
1359

1360
                self.print_closure_args(&decl, body)?;
1361
                self.s.space()?;
1362

1363
                // this is a bare expression
1364
                self.ann.nested(self, Nested::Body(body))?;
1365
                self.end()?; // need to close a box
1366 1367 1368 1369

                // 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 已提交
1370
                self.ibox(0)?;
1371
            }
C
csmoe 已提交
1372
            hir::ExprKind::Block(ref blk, opt_label) => {
1373
                if let Some(label) = opt_label {
1374
                    self.print_ident(label.ident)?;
1375 1376
                    self.word_space(":")?;
                }
1377
                // containing cbox, will be closed by print-block at }
J
Jorge Aparicio 已提交
1378
                self.cbox(indent_unit)?;
1379
                // head-box, will be closed by print-block after {
J
Jorge Aparicio 已提交
1380 1381
                self.ibox(0)?;
                self.print_block(&blk)?;
1382
            }
C
csmoe 已提交
1383
            hir::ExprKind::Assign(ref lhs, ref rhs) => {
1384 1385
                let prec = AssocOp::Assign.precedence() as i8;
                self.print_expr_maybe_paren(&lhs, prec + 1)?;
1386
                self.s.space()?;
J
Jorge Aparicio 已提交
1387
                self.word_space("=")?;
1388
                self.print_expr_maybe_paren(&rhs, prec)?;
1389
            }
C
csmoe 已提交
1390
            hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
1391 1392
                let prec = AssocOp::Assign.precedence() as i8;
                self.print_expr_maybe_paren(&lhs, prec + 1)?;
1393 1394
                self.s.space()?;
                self.s.word(op.node.as_str())?;
J
Jorge Aparicio 已提交
1395
                self.word_space("=")?;
1396
                self.print_expr_maybe_paren(&rhs, prec)?;
1397
            }
C
csmoe 已提交
1398
            hir::ExprKind::Field(ref expr, ident) => {
1399
                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
1400
                self.s.word(".")?;
1401
                self.print_ident(ident)?;
1402
            }
C
csmoe 已提交
1403
            hir::ExprKind::Index(ref expr, ref index) => {
1404
                self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX)?;
1405
                self.s.word("[")?;
J
Jorge Aparicio 已提交
1406
                self.print_expr(&index)?;
1407
                self.s.word("]")?;
1408
            }
C
csmoe 已提交
1409
            hir::ExprKind::Path(ref qpath) => {
1410
                self.print_qpath(qpath, true)?
1411
            }
C
csmoe 已提交
1412
            hir::ExprKind::Break(destination, ref opt_expr) => {
1413 1414
                self.s.word("break")?;
                self.s.space()?;
1415
                if let Some(label) = destination.label {
1416
                    self.print_ident(label.ident)?;
1417
                    self.s.space()?;
1418
                }
1419
                if let Some(ref expr) = *opt_expr {
1420
                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP)?;
1421
                    self.s.space()?;
1422
                }
1423
            }
C
csmoe 已提交
1424
            hir::ExprKind::Continue(destination) => {
1425 1426
                self.s.word("continue")?;
                self.s.space()?;
1427
                if let Some(label) = destination.label {
1428
                    self.print_ident(label.ident)?;
1429
                    self.s.space()?
1430 1431
                }
            }
C
csmoe 已提交
1432
            hir::ExprKind::Ret(ref result) => {
1433
                self.s.word("return")?;
L
ljedrz 已提交
1434 1435 1436
                if let Some(ref expr) = *result {
                    self.s.word(" ")?;
                    self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
1437 1438
                }
            }
C
csmoe 已提交
1439
            hir::ExprKind::InlineAsm(ref a, ref outputs, ref inputs) => {
1440
                self.s.word("asm!")?;
J
Jorge Aparicio 已提交
1441
                self.popen()?;
1442
                self.print_string(&a.asm.as_str(), a.asm_str_style)?;
J
Jorge Aparicio 已提交
1443
                self.word_space(":")?;
1444

1445
                let mut out_idx = 0;
J
Jorge Aparicio 已提交
1446
                self.commasep(Inconsistent, &a.outputs, |s, out| {
1447 1448
                    let constraint = out.constraint.as_str();
                    let mut ch = constraint.chars();
1449 1450 1451 1452
                    match ch.next() {
                        Some('=') if out.is_rw => {
                            s.print_string(&format!("+{}", ch.as_str()),
                                           ast::StrStyle::Cooked)?
J
Jose Narvaez 已提交
1453
                        }
1454
                        _ => s.print_string(&constraint, ast::StrStyle::Cooked)?,
J
Jose Narvaez 已提交
1455
                    }
J
Jorge Aparicio 已提交
1456 1457 1458
                    s.popen()?;
                    s.print_expr(&outputs[out_idx])?;
                    s.pclose()?;
1459
                    out_idx += 1;
J
Jose Narvaez 已提交
1460
                    Ok(())
J
Jorge Aparicio 已提交
1461
                })?;
1462
                self.s.space()?;
J
Jorge Aparicio 已提交
1463
                self.word_space(":")?;
1464

1465
                let mut in_idx = 0;
J
Jorge Aparicio 已提交
1466
                self.commasep(Inconsistent, &a.inputs, |s, co| {
1467
                    s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
J
Jorge Aparicio 已提交
1468 1469 1470
                    s.popen()?;
                    s.print_expr(&inputs[in_idx])?;
                    s.pclose()?;
1471
                    in_idx += 1;
J
Jose Narvaez 已提交
1472
                    Ok(())
J
Jorge Aparicio 已提交
1473
                })?;
1474
                self.s.space()?;
J
Jorge Aparicio 已提交
1475
                self.word_space(":")?;
1476

J
Jorge Aparicio 已提交
1477
                self.commasep(Inconsistent, &a.clobbers, |s, co| {
1478
                    s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
J
Jose Narvaez 已提交
1479
                    Ok(())
J
Jorge Aparicio 已提交
1480
                })?;
1481

J
Jose Narvaez 已提交
1482
                let mut options = vec![];
1483 1484 1485 1486 1487 1488
                if a.volatile {
                    options.push("volatile");
                }
                if a.alignstack {
                    options.push("alignstack");
                }
1489
                if a.dialect == ast::AsmDialect::Intel {
1490 1491 1492 1493
                    options.push("intel");
                }

                if !options.is_empty() {
1494
                    self.s.space()?;
J
Jorge Aparicio 已提交
1495 1496 1497
                    self.word_space(":")?;
                    self.commasep(Inconsistent, &options, |s, &co| {
                        s.print_string(co, ast::StrStyle::Cooked)?;
J
Jose Narvaez 已提交
1498
                        Ok(())
J
Jorge Aparicio 已提交
1499
                    })?;
1500 1501
                }

J
Jorge Aparicio 已提交
1502
                self.pclose()?;
1503
            }
C
csmoe 已提交
1504
            hir::ExprKind::Yield(ref expr) => {
J
John Kåre Alsaker 已提交
1505
                self.word_space("yield")?;
1506
                self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
J
John Kåre Alsaker 已提交
1507
            }
1508 1509 1510 1511 1512
            hir::ExprKind::Err => {
                self.popen()?;
                self.s.word("/*ERROR*/")?;
                self.pclose()?;
            }
1513
        }
V
varkor 已提交
1514
        self.ann.post(self, AnnNode::Expr(expr))?;
1515 1516 1517 1518
        self.end()
    }

    pub fn print_local_decl(&mut self, loc: &hir::Local) -> io::Result<()> {
J
Jorge Aparicio 已提交
1519
        self.print_pat(&loc.pat)?;
1520
        if let Some(ref ty) = loc.ty {
J
Jorge Aparicio 已提交
1521 1522
            self.word_space(":")?;
            self.print_type(&ty)?;
1523 1524 1525 1526 1527
        }
        Ok(())
    }

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

1531 1532
    pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
        if ident.is_raw_guess() {
1533
            self.s.word(format!("r#{}", ident.name))?;
1534
        } else {
1535
            self.s.word(ident.as_str().to_string())?;
1536
        }
V
varkor 已提交
1537
        self.ann.post(self, AnnNode::Name(&ident.name))
1538 1539 1540
    }

    pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
1541
        self.print_ident(ast::Ident::with_empty_ctxt(name))
1542 1543
    }

N
Nick Cameron 已提交
1544
    pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> {
J
Jorge Aparicio 已提交
1545
        self.print_local_decl(loc)?;
1546
        self.s.space()?;
J
Jorge Aparicio 已提交
1547
        self.word_space("in")?;
1548 1549 1550
        self.print_expr(coll)
    }

1551 1552 1553 1554
    pub fn print_path(&mut self,
                      path: &hir::Path,
                      colons_before_params: bool)
                      -> io::Result<()> {
1555
        self.maybe_print_comment(path.span.lo())?;
1556

1557 1558
        for (i, segment) in path.segments.iter().enumerate() {
            if i > 0 {
1559
                self.s.word("::")?
1560
            }
1561
            if segment.ident.name != kw::PathRoot {
1562
               self.print_ident(segment.ident)?;
1563
               segment.with_generic_args(|generic_args| {
1564
                   self.print_generic_args(generic_args, segment.infer_types,
1565
                                           colons_before_params)
1566
               })?;
1567
            }
1568 1569 1570 1571 1572
        }

        Ok(())
    }

1573
    pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> {
1574
        if segment.ident.name != kw::PathRoot {
1575 1576 1577 1578 1579 1580 1581 1582
           self.print_ident(segment.ident)?;
           segment.with_generic_args(|generic_args| {
               self.print_generic_args(generic_args, segment.infer_types, false)
           })?;
        }
        Ok(())
    }

1583 1584 1585 1586
    pub fn print_qpath(&mut self,
                       qpath: &hir::QPath,
                       colons_before_params: bool)
                       -> io::Result<()> {
1587 1588 1589 1590 1591
        match *qpath {
            hir::QPath::Resolved(None, ref path) => {
                self.print_path(path, colons_before_params)
            }
            hir::QPath::Resolved(Some(ref qself), ref path) => {
1592
                self.s.word("<")?;
1593
                self.print_type(qself)?;
1594
                self.s.space()?;
1595 1596
                self.word_space("as")?;

1597 1598
                for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() {
                    if i > 0 {
1599
                        self.s.word("::")?
1600
                    }
1601
                    if segment.ident.name != kw::PathRoot {
1602
                        self.print_ident(segment.ident)?;
1603 1604 1605 1606
                        segment.with_generic_args(|generic_args| {
                            self.print_generic_args(generic_args,
                                                    segment.infer_types,
                                                    colons_before_params)
1607
                        })?;
1608
                    }
1609 1610
                }

1611 1612
                self.s.word(">")?;
                self.s.word("::")?;
1613
                let item_segment = path.segments.last().unwrap();
1614
                self.print_ident(item_segment.ident)?;
1615 1616 1617 1618
                item_segment.with_generic_args(|generic_args| {
                    self.print_generic_args(generic_args,
                                            item_segment.infer_types,
                                            colons_before_params)
1619
                })
1620 1621
            }
            hir::QPath::TypeRelative(ref qself, ref item_segment) => {
1622
                self.s.word("<")?;
1623
                self.print_type(qself)?;
1624 1625
                self.s.word(">")?;
                self.s.word("::")?;
1626
                self.print_ident(item_segment.ident)?;
1627 1628 1629 1630
                item_segment.with_generic_args(|generic_args| {
                    self.print_generic_args(generic_args,
                                            item_segment.infer_types,
                                            colons_before_params)
1631
                })
1632
            }
1633 1634 1635
        }
    }

1636 1637
    fn print_generic_args(&mut self,
                             generic_args: &hir::GenericArgs,
1638
                             infer_types: bool,
1639
                             colons_before_params: bool)
N
Nick Cameron 已提交
1640
                             -> io::Result<()> {
1641
        if generic_args.parenthesized {
1642
            self.s.word("(")?;
1643
            self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty))?;
1644
            self.s.word(")")?;
1645

1646 1647
            self.space_if_not_bol()?;
            self.word_space("->")?;
1648
            self.print_type(generic_args.bindings[0].ty())?;
1649 1650 1651 1652 1653 1654 1655 1656 1657
        } else {
            let start = if colons_before_params { "::<" } else { "<" };
            let empty = Cell::new(true);
            let start_or_comma = |this: &mut Self| {
                if empty.get() {
                    empty.set(false);
                    this.s.word(start)
                } else {
                    this.word_space(",")
1658
                }
1659
            };
1660

V
varkor 已提交
1661 1662 1663 1664 1665 1666
            let mut nonelided_generic_args: bool = false;
            let elide_lifetimes = generic_args.args.iter().all(|arg| match arg {
                GenericArg::Lifetime(lt) => lt.is_elided(),
                _ => {
                    nonelided_generic_args = true;
                    true
1667
                }
V
varkor 已提交
1668 1669 1670
            });

            if nonelided_generic_args {
1671
                start_or_comma(self)?;
1672 1673
                self.commasep(Inconsistent, &generic_args.args, |s, generic_arg| {
                    match generic_arg {
V
varkor 已提交
1674 1675
                        GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
                        GenericArg::Lifetime(_) => Ok(()),
1676
                        GenericArg::Type(ty) => s.print_type(ty),
V
varkor 已提交
1677
                        GenericArg::Const(ct) => s.print_anon_const(&ct.value),
1678
                    }
1679
                })?;
V
varkor 已提交
1680 1681
            }

1682 1683
            // FIXME(eddyb): this would leak into error messages (e.g.,
            // "non-exhaustive patterns: `Some::<..>(_)` not covered").
1684
            if infer_types && false {
1685 1686
                start_or_comma(self)?;
                self.s.word("..")?;
1687 1688
            }

1689
            for binding in generic_args.bindings.iter() {
1690
                start_or_comma(self)?;
1691
                self.print_ident(binding.ident)?;
1692
                self.s.space()?;
1693 1694 1695 1696 1697 1698 1699 1700 1701
                match generic_args.bindings[0].kind {
                    hir::TypeBindingKind::Equality { ref ty } => {
                        self.word_space("=")?;
                        self.print_type(ty)?;
                    }
                    hir::TypeBindingKind::Constraint { ref bounds } => {
                        self.print_bounds(":", bounds)?;
                    }
                }
1702
            }
1703

1704 1705
            if !empty.get() {
                self.s.word(">")?
1706 1707 1708 1709 1710 1711 1712
            }
        }

        Ok(())
    }

    pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
1713
        self.maybe_print_comment(pat.span.lo())?;
V
varkor 已提交
1714
        self.ann.pre(self, AnnNode::Pat(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 {
1718
            PatKind::Wild => self.s.word("_")?,
L
ljedrz 已提交
1719
            PatKind::Binding(binding_mode, _, ident, ref sub) => {
1720
                match binding_mode {
1721
                    hir::BindingAnnotation::Ref => {
J
Jorge Aparicio 已提交
1722
                        self.word_nbsp("ref")?;
1723
                        self.print_mutability(hir::MutImmutable)?;
1724
                    }
1725 1726 1727 1728 1729 1730
                    hir::BindingAnnotation::RefMut => {
                        self.word_nbsp("ref")?;
                        self.print_mutability(hir::MutMutable)?;
                    }
                    hir::BindingAnnotation::Unannotated => {}
                    hir::BindingAnnotation::Mutable => {
J
Jorge Aparicio 已提交
1731
                        self.word_nbsp("mut")?;
1732 1733
                    }
                }
1734
                self.print_ident(ident)?;
1735
                if let Some(ref p) = *sub {
1736
                    self.s.word("@")?;
1737
                    self.print_pat(&p)?;
1738 1739
                }
            }
1740 1741
            PatKind::TupleStruct(ref qpath, ref elts, ddpos) => {
                self.print_qpath(qpath, true)?;
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(",")?;
                    }
1748
                    self.s.word("..")?;
1749
                    if ddpos != elts.len() {
1750
                        self.s.word(",")?;
1751
                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
1752
                    }
1753
                } else {
1754
                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
1755
                }
1756
                self.pclose()?;
1757
            }
1758 1759
            PatKind::Path(ref qpath) => {
                self.print_qpath(qpath, true)?;
1760
            }
1761 1762
            PatKind::Struct(ref qpath, ref fields, etc) => {
                self.print_qpath(qpath, true)?;
J
Jorge Aparicio 已提交
1763 1764 1765
                self.nbsp()?;
                self.word_space("{")?;
                self.commasep_cmnt(Consistent,
J
Jorge Aparicio 已提交
1766 1767 1768 1769
                                   &fields[..],
                                   |s, f| {
                                       s.cbox(indent_unit)?;
                                       if !f.node.is_shorthand {
1770
                                           s.print_ident(f.node.ident)?;
J
Jorge Aparicio 已提交
1771 1772 1773 1774 1775 1776
                                           s.word_nbsp(":")?;
                                       }
                                       s.print_pat(&f.node.pat)?;
                                       s.end()
                                   },
                                   |f| f.node.pat.span)?;
1777
                if etc {
N
Nick Cameron 已提交
1778
                    if !fields.is_empty() {
J
Jorge Aparicio 已提交
1779
                        self.word_space(",")?;
N
Nick Cameron 已提交
1780
                    }
1781
                    self.s.word("..")?;
1782
                }
1783 1784
                self.s.space()?;
                self.s.word("}")?;
1785
            }
1786
            PatKind::Tuple(ref elts, ddpos) => {
J
Jorge Aparicio 已提交
1787
                self.popen()?;
1788 1789 1790 1791 1792
                if let Some(ddpos) = ddpos {
                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
                    if ddpos != 0 {
                        self.word_space(",")?;
                    }
1793
                    self.s.word("..")?;
1794
                    if ddpos != elts.len() {
1795
                        self.s.word(",")?;
1796 1797 1798 1799 1800
                        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 {
1801
                        self.s.word(",")?;
1802
                    }
1803
                }
J
Jorge Aparicio 已提交
1804
                self.pclose()?;
1805
            }
1806
            PatKind::Box(ref inner) => {
1807 1808 1809 1810
                let is_range_inner = match inner.node {
                    PatKind::Range(..) => true,
                    _ => false,
                };
1811
                self.s.word("box ")?;
1812 1813 1814
                if is_range_inner {
                    self.popen()?;
                }
J
Jorge Aparicio 已提交
1815
                self.print_pat(&inner)?;
1816 1817 1818
                if is_range_inner {
                    self.pclose()?;
                }
1819
            }
1820
            PatKind::Ref(ref inner, mutbl) => {
1821 1822 1823 1824
                let is_range_inner = match inner.node {
                    PatKind::Range(..) => true,
                    _ => false,
                };
1825
                self.s.word("&")?;
1826
                if mutbl == hir::MutMutable {
1827
                    self.s.word("mut ")?;
1828
                }
1829 1830 1831
                if is_range_inner {
                    self.popen()?;
                }
J
Jorge Aparicio 已提交
1832
                self.print_pat(&inner)?;
1833 1834 1835
                if is_range_inner {
                    self.pclose()?;
                }
1836
            }
J
Jorge Aparicio 已提交
1837
            PatKind::Lit(ref e) => self.print_expr(&e)?,
1838
            PatKind::Range(ref begin, ref end, ref end_kind) => {
J
Jorge Aparicio 已提交
1839
                self.print_expr(&begin)?;
1840
                self.s.space()?;
1841
                match *end_kind {
1842 1843
                    RangeEnd::Included => self.s.word("...")?,
                    RangeEnd::Excluded => self.s.word("..")?,
1844
                }
J
Jorge Aparicio 已提交
1845
                self.print_expr(&end)?;
1846
            }
1847
            PatKind::Slice(ref before, ref slice, ref after) => {
1848
                self.s.word("[")?;
J
Jorge Aparicio 已提交
1849
                self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))?;
1850
                if let Some(ref p) = *slice {
N
Nick Cameron 已提交
1851
                    if !before.is_empty() {
J
Jorge Aparicio 已提交
1852
                        self.word_space(",")?;
N
Nick Cameron 已提交
1853
                    }
1854 1855 1856
                    if let PatKind::Wild = p.node {
                        // Print nothing
                    } else {
J
Jorge Aparicio 已提交
1857
                        self.print_pat(&p)?;
1858
                    }
1859
                    self.s.word("..")?;
N
Nick Cameron 已提交
1860
                    if !after.is_empty() {
J
Jorge Aparicio 已提交
1861
                        self.word_space(",")?;
N
Nick Cameron 已提交
1862
                    }
1863
                }
J
Jorge Aparicio 已提交
1864
                self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p))?;
1865
                self.s.word("]")?;
1866 1867
            }
        }
V
varkor 已提交
1868
        self.ann.post(self, AnnNode::Pat(pat))
1869 1870
    }

1871
    pub fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
1872 1873 1874
        // I have no idea why this check is necessary, but here it
        // is :(
        if arm.attrs.is_empty() {
1875
            self.s.space()?;
1876
        }
J
Jorge Aparicio 已提交
1877 1878 1879
        self.cbox(indent_unit)?;
        self.ibox(0)?;
        self.print_outer_attributes(&arm.attrs)?;
1880 1881 1882 1883 1884
        let mut first = true;
        for p in &arm.pats {
            if first {
                first = false;
            } else {
1885
                self.s.space()?;
J
Jorge Aparicio 已提交
1886
                self.word_space("|")?;
1887
            }
J
Jorge Aparicio 已提交
1888
            self.print_pat(&p)?;
1889
        }
1890
        self.s.space()?;
F
F001 已提交
1891 1892 1893 1894 1895 1896 1897 1898
        if let Some(ref g) = arm.guard {
            match g {
                hir::Guard::If(e) => {
                    self.word_space("if")?;
                    self.print_expr(&e)?;
                    self.s.space()?;
                }
            }
1899
        }
J
Jorge Aparicio 已提交
1900
        self.word_space("=>")?;
1901 1902

        match arm.body.node {
C
csmoe 已提交
1903
            hir::ExprKind::Block(ref blk, opt_label) => {
1904
                if let Some(label) = opt_label {
1905
                    self.print_ident(label.ident)?;
1906 1907
                    self.word_space(":")?;
                }
1908
                // the block will close the pattern's ibox
J
Jorge Aparicio 已提交
1909
                self.print_block_unclosed_indent(&blk, indent_unit)?;
1910 1911 1912

                // If it is a user-provided unsafe block, print a comma after it
                if let hir::UnsafeBlock(hir::UserProvided) = blk.rules {
1913
                    self.s.word(",")?;
1914 1915 1916
                }
            }
            _ => {
J
Jorge Aparicio 已提交
1917 1918
                self.end()?; // close the ibox for the pattern
                self.print_expr(&arm.body)?;
1919
                self.s.word(",")?;
1920 1921 1922 1923 1924 1925 1926
            }
        }
        self.end() // close enclosing cbox
    }

    pub fn print_fn(&mut self,
                    decl: &hir::FnDecl,
W
Without Boats 已提交
1927
                    header: hir::FnHeader,
V
Vadim Petrochenkov 已提交
1928
                    name: Option<ast::Name>,
1929
                    generics: &hir::Generics,
1930
                    vis: &hir::Visibility,
1931
                    arg_names: &[ast::Ident],
1932
                    body_id: Option<hir::BodyId>)
N
Nick Cameron 已提交
1933
                    -> io::Result<()> {
W
Without Boats 已提交
1934
        self.print_fn_header_info(header, vis)?;
1935 1936

        if let Some(name) = name {
J
Jorge Aparicio 已提交
1937 1938
            self.nbsp()?;
            self.print_name(name)?;
1939
        }
1940
        self.print_generic_params(&generics.params)?;
1941

J
Jorge Aparicio 已提交
1942
        self.popen()?;
1943 1944 1945 1946 1947
        let mut i = 0;
        // Make sure we aren't supplied *both* `arg_names` and `body_id`.
        assert!(arg_names.is_empty() || body_id.is_none());
        self.commasep(Inconsistent, &decl.inputs, |s, ty| {
            s.ibox(indent_unit)?;
1948
            if let Some(arg_name) = arg_names.get(i) {
1949
                s.s.word(arg_name.as_str().to_string())?;
1950 1951
                s.s.word(":")?;
                s.s.space()?;
1952 1953
            } else if let Some(body_id) = body_id {
                s.ann.nested(s, Nested::BodyArgPat(body_id, i))?;
1954 1955
                s.s.word(":")?;
                s.s.space()?;
1956 1957 1958 1959 1960
            }
            i += 1;
            s.print_type(ty)?;
            s.end()
        })?;
D
Dan Robertson 已提交
1961
        if decl.c_variadic {
1962
            self.s.word(", ...")?;
1963
        }
J
Jorge Aparicio 已提交
1964
        self.pclose()?;
1965

1966 1967
        self.print_fn_output(decl)?;
        self.print_where_clause(&generics.where_clause)
1968 1969
    }

1970
    fn print_closure_args(&mut self, decl: &hir::FnDecl, body_id: hir::BodyId) -> io::Result<()> {
1971
        self.s.word("|")?;
1972 1973 1974 1975
        let mut i = 0;
        self.commasep(Inconsistent, &decl.inputs, |s, ty| {
            s.ibox(indent_unit)?;

1976
            s.ann.nested(s, Nested::BodyArgPat(body_id, i))?;
1977 1978
            i += 1;

C
TyKind  
csmoe 已提交
1979
            if let hir::TyKind::Infer = ty.node {
1980 1981
                // Print nothing
            } else {
1982 1983
                s.s.word(":")?;
                s.s.space()?;
1984 1985 1986 1987
                s.print_type(ty)?;
            }
            s.end()
        })?;
1988
        self.s.word("|")?;
1989 1990 1991 1992 1993

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

J
Jorge Aparicio 已提交
1994 1995
        self.space_if_not_bol()?;
        self.word_space("->")?;
1996 1997
        match decl.output {
            hir::Return(ref ty) => {
J
Jorge Aparicio 已提交
1998
                self.print_type(&ty)?;
1999
                self.maybe_print_comment(ty.span.lo())
2000 2001 2002 2003 2004
            }
            hir::DefaultReturn(..) => unreachable!(),
        }
    }

N
Nick Cameron 已提交
2005
    pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) -> io::Result<()> {
2006 2007 2008 2009 2010 2011
        match capture_clause {
            hir::CaptureByValue => self.word_space("move"),
            hir::CaptureByRef => Ok(()),
        }
    }

2012 2013
    pub fn print_bounds(&mut self, prefix: &'static str, bounds: &[hir::GenericBound])
                        -> io::Result<()> {
2014
        if !bounds.is_empty() {
2015
            self.s.word(prefix)?;
2016 2017
            let mut first = true;
            for bound in bounds {
2018 2019 2020
                if !(first && prefix.is_empty()) {
                    self.nbsp()?;
                }
2021 2022 2023
                if first {
                    first = false;
                } else {
J
Jorge Aparicio 已提交
2024
                    self.word_space("+")?;
2025 2026
                }

2027
                match bound {
V
varkor 已提交
2028
                    GenericBound::Trait(tref, modifier) => {
2029 2030 2031 2032
                        if modifier == &TraitBoundModifier::Maybe {
                            self.s.word("?")?;
                        }
                        self.print_poly_trait_ref(tref)?;
2033
                    }
V
varkor 已提交
2034
                    GenericBound::Outlives(lt) => {
2035
                        self.print_lifetime(lt)?;
2036
                    }
2037
                }
2038 2039
            }
        }
2040
        Ok(())
2041 2042
    }

V
varkor 已提交
2043
    pub fn print_generic_params(&mut self, generic_params: &[GenericParam]) -> io::Result<()> {
2044 2045
        if !generic_params.is_empty() {
            self.s.word("<")?;
2046

2047
            self.commasep(Inconsistent, generic_params, |s, param| {
V
varkor 已提交
2048
                s.print_generic_param(param)
2049
            })?;
2050

2051
            self.s.word(">")?;
2052 2053 2054 2055
        }
        Ok(())
    }

V
varkor 已提交
2056
    pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> {
V
varkor 已提交
2057 2058 2059 2060
        if let GenericParamKind::Const { .. } = param.kind {
            self.word_space("const")?;
        }

V
Vadim Petrochenkov 已提交
2061
        self.print_ident(param.name.ident())?;
V
varkor 已提交
2062

V
varkor 已提交
2063
        match param.kind {
V
varkor 已提交
2064
            GenericParamKind::Lifetime { .. } => {
V
varkor 已提交
2065
                let mut sep = ":";
V
varkor 已提交
2066 2067
                for bound in &param.bounds {
                    match bound {
V
varkor 已提交
2068
                        GenericBound::Outlives(lt) => {
V
varkor 已提交
2069 2070 2071 2072 2073 2074
                            self.s.word(sep)?;
                            self.print_lifetime(lt)?;
                            sep = "+";
                        }
                        _ => bug!(),
                    }
V
varkor 已提交
2075 2076 2077
                }
                Ok(())
            }
V
varkor 已提交
2078 2079
            GenericParamKind::Type { ref default, .. } => {
                self.print_bounds(":", &param.bounds)?;
V
varkor 已提交
2080 2081 2082 2083 2084 2085 2086 2087
                match default {
                    Some(default) => {
                        self.s.space()?;
                        self.word_space("=")?;
                        self.print_type(&default)
                    }
                    _ => Ok(()),
                }
2088
            }
V
varkor 已提交
2089 2090 2091 2092
            GenericParamKind::Const { ref ty } => {
                self.word_space(":")?;
                self.print_type(ty)
            }
2093 2094 2095
        }
    }

V
varkor 已提交
2096
    pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
V
Vadim Petrochenkov 已提交
2097
        self.print_ident(lifetime.name.ident())
V
varkor 已提交
2098 2099
    }

N
Nick Cameron 已提交
2100
    pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> {
2101
        if where_clause.predicates.is_empty() {
J
Jose Narvaez 已提交
2102
            return Ok(());
2103 2104
        }

2105
        self.s.space()?;
J
Jorge Aparicio 已提交
2106
        self.word_space("where")?;
2107 2108 2109

        for (i, predicate) in where_clause.predicates.iter().enumerate() {
            if i != 0 {
J
Jorge Aparicio 已提交
2110
                self.word_space(",")?;
2111 2112 2113
            }

            match predicate {
2114 2115 2116 2117 2118 2119 2120
                &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
                    ref bound_generic_params,
                    ref bounded_ty,
                    ref bounds,
                    ..
                }) => {
                    self.print_formal_generic_params(bound_generic_params)?;
J
Jorge Aparicio 已提交
2121 2122
                    self.print_type(&bounded_ty)?;
                    self.print_bounds(":", bounds)?;
2123 2124 2125 2126
                }
                &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
                                                                                ref bounds,
                                                                                ..}) => {
J
Jorge Aparicio 已提交
2127
                    self.print_lifetime(lifetime)?;
2128
                    self.s.word(":")?;
2129 2130

                    for (i, bound) in bounds.iter().enumerate() {
V
varkor 已提交
2131
                        match bound {
V
varkor 已提交
2132
                            GenericBound::Outlives(lt) => {
V
varkor 已提交
2133 2134 2135 2136
                                self.print_lifetime(lt)?;
                            }
                            _ => bug!(),
                        }
2137 2138

                        if i != 0 {
2139
                            self.s.word(":")?;
2140 2141 2142
                        }
                    }
                }
2143 2144 2145 2146
                &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref lhs_ty,
                                                                        ref rhs_ty,
                                                                        ..}) => {
                    self.print_type(lhs_ty)?;
2147
                    self.s.space()?;
J
Jorge Aparicio 已提交
2148
                    self.word_space("=")?;
2149
                    self.print_type(rhs_ty)?;
2150 2151 2152 2153 2154 2155 2156
                }
            }
        }

        Ok(())
    }

N
Nick Cameron 已提交
2157
    pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> {
2158 2159 2160 2161 2162 2163 2164
        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 已提交
2165
        self.print_mutability(mt.mutbl)?;
2166
        self.print_type(&mt.ty)
2167 2168 2169 2170 2171 2172 2173
    }

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

J
Jorge Aparicio 已提交
2174 2175 2176
        self.space_if_not_bol()?;
        self.ibox(indent_unit)?;
        self.word_space("->")?;
2177 2178
        match decl.output {
            hir::DefaultReturn(..) => unreachable!(),
J
Jorge Aparicio 已提交
2179
            hir::Return(ref ty) => self.print_type(&ty)?,
2180
        }
J
Jorge Aparicio 已提交
2181
        self.end()?;
2182 2183

        match decl.output {
2184
            hir::Return(ref output) => self.maybe_print_comment(output.span.lo()),
N
Nick Cameron 已提交
2185
            _ => Ok(()),
2186 2187 2188 2189
        }
    }

    pub fn print_ty_fn(&mut self,
2190
                       abi: Abi,
2191 2192
                       unsafety: hir::Unsafety,
                       decl: &hir::FnDecl,
2193
                       name: Option<ast::Name>,
2194
                       generic_params: &[hir::GenericParam],
2195
                       arg_names: &[ast::Ident])
2196
                       -> io::Result<()> {
J
Jorge Aparicio 已提交
2197
        self.ibox(indent_unit)?;
2198
        if !generic_params.is_empty() {
2199
            self.s.word("for")?;
2200
            self.print_generic_params(generic_params)?;
2201 2202
        }
        let generics = hir::Generics {
2203
            params: hir::HirVec::new(),
2204
            where_clause: hir::WhereClause {
L
ljedrz 已提交
2205
                hir_id: hir::DUMMY_HIR_ID,
2206
                predicates: hir::HirVec::new(),
2207
            },
2208
            span: syntax_pos::DUMMY_SP,
2209
        };
J
Jorge Aparicio 已提交
2210
        self.print_fn(decl,
W
Without Boats 已提交
2211
                      hir::FnHeader {
2212 2213 2214 2215
                          unsafety,
                          abi,
                          constness: hir::Constness::NotConst,
                          asyncness: hir::IsAsync::NotAsync,
W
Without Boats 已提交
2216
                      },
J
Jorge Aparicio 已提交
2217 2218
                      name,
                      &generics,
2219 2220
                      &Spanned { span: syntax_pos::DUMMY_SP,
                                 node: hir::VisibilityKind::Inherited },
2221
                      arg_names,
2222
                      None)?;
2223 2224 2225
        self.end()
    }

N
Nick Cameron 已提交
2226
    pub fn maybe_print_trailing_comment(&mut self,
2227
                                        span: syntax_pos::Span,
2228
                                        next_pos: Option<BytePos>)
N
Nick Cameron 已提交
2229
                                        -> io::Result<()> {
2230 2231
        let cm = match self.cm {
            Some(cm) => cm,
N
Nick Cameron 已提交
2232
            _ => return Ok(()),
2233
        };
2234 2235 2236 2237
        if let Some(ref cmnt) = self.next_comment() {
            if (*cmnt).style != comments::Trailing {
                return Ok(());
            }
2238
            let span_line = cm.lookup_char_pos(span.hi());
2239 2240 2241 2242 2243
            let comment_line = cm.lookup_char_pos((*cmnt).pos);
            let mut next = (*cmnt).pos + BytePos(1);
            if let Some(p) = next_pos {
                next = p;
            }
2244
            if span.hi() < (*cmnt).pos && (*cmnt).pos < next &&
2245 2246
               span_line.line == comment_line.line {
                self.print_comment(cmnt)?;
2247 2248 2249 2250 2251 2252 2253 2254 2255
            }
        }
        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() {
2256
            self.s.hardbreak()?;
2257
        }
L
leonardo.yvens 已提交
2258 2259
        while let Some(ref cmnt) = self.next_comment() {
            self.print_comment(cmnt)?
2260 2261 2262 2263 2264
        }
        Ok(())
    }

    pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
2265
                                                  opt_abi: Option<Abi>)
N
Nick Cameron 已提交
2266
                                                  -> io::Result<()> {
2267
        match opt_abi {
2268
            Some(Abi::Rust) => Ok(()),
2269
            Some(abi) => {
J
Jorge Aparicio 已提交
2270
                self.word_nbsp("extern")?;
2271
                self.word_nbsp(abi.to_string())
2272
            }
N
Nick Cameron 已提交
2273
            None => Ok(()),
2274 2275 2276
        }
    }

2277
    pub fn print_extern_opt_abi(&mut self, opt_abi: Option<Abi>) -> io::Result<()> {
2278 2279
        match opt_abi {
            Some(abi) => {
J
Jorge Aparicio 已提交
2280
                self.word_nbsp("extern")?;
2281
                self.word_nbsp(abi.to_string())
2282
            }
N
Nick Cameron 已提交
2283
            None => Ok(()),
2284 2285 2286 2287
        }
    }

    pub fn print_fn_header_info(&mut self,
W
Without Boats 已提交
2288
                                header: hir::FnHeader,
2289
                                vis: &hir::Visibility)
N
Nick Cameron 已提交
2290
                                -> io::Result<()> {
2291
        self.s.word(visibility_qualified(vis, ""))?;
2292

W
Without Boats 已提交
2293
        match header.constness {
2294
            hir::Constness::NotConst => {}
J
Jorge Aparicio 已提交
2295
            hir::Constness::Const => self.word_nbsp("const")?,
2296 2297
        }

W
Without Boats 已提交
2298 2299 2300 2301 2302 2303 2304 2305
        match header.asyncness {
            hir::IsAsync::NotAsync => {}
            hir::IsAsync::Async => self.word_nbsp("async")?,
        }

        self.print_unsafety(header.unsafety)?;

        if header.abi != Abi::Rust {
J
Jorge Aparicio 已提交
2306
            self.word_nbsp("extern")?;
2307
            self.word_nbsp(header.abi.to_string())?;
2308 2309
        }

2310
        self.s.word("fn")
2311 2312 2313 2314 2315 2316 2317 2318
    }

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

    pub fn print_is_auto(&mut self, s: hir::IsAuto) -> io::Result<()> {
        match s {
            hir::IsAuto::Yes => self.word_nbsp("auto"),
            hir::IsAuto::No => Ok(()),
        }
    }
2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337
}

// 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 {
C
csmoe 已提交
2338 2339 2340 2341
        hir::ExprKind::Match(..) |
        hir::ExprKind::Block(..) |
        hir::ExprKind::While(..) |
        hir::ExprKind::Loop(..) => false,
N
Nick Cameron 已提交
2342
        _ => true,
2343 2344 2345 2346 2347 2348
    }
}

/// 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.
C
csmoe 已提交
2349
fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool {
2350
    match *stmt {
2351 2352 2353 2354
        hir::StmtKind::Local(_) => true,
        hir::StmtKind::Item(_) => false,
        hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e),
        hir::StmtKind::Semi(..) => false,
2355 2356
    }
}
2357

C
csmoe 已提交
2358
fn bin_op_to_assoc_op(op: hir::BinOpKind) -> AssocOp {
M
Mark Mansi 已提交
2359
    use crate::hir::BinOpKind::*;
2360
    match op {
C
csmoe 已提交
2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381
        Add => AssocOp::Add,
        Sub => AssocOp::Subtract,
        Mul => AssocOp::Multiply,
        Div => AssocOp::Divide,
        Rem => AssocOp::Modulus,

        And => AssocOp::LAnd,
        Or => AssocOp::LOr,

        BitXor => AssocOp::BitXor,
        BitAnd => AssocOp::BitAnd,
        BitOr => AssocOp::BitOr,
        Shl => AssocOp::ShiftLeft,
        Shr => AssocOp::ShiftRight,

        Eq => AssocOp::Equal,
        Lt => AssocOp::Less,
        Le => AssocOp::LessEqual,
        Ne => AssocOp::NotEqual,
        Ge => AssocOp::GreaterEqual,
        Gt => AssocOp::Greater,
2382 2383 2384
    }
}

2385 2386
/// Expressions that syntactically contain an "exterior" struct literal i.e., not surrounded by any
/// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
2387 2388 2389
/// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
fn contains_exterior_struct_lit(value: &hir::Expr) -> bool {
    match value.node {
C
csmoe 已提交
2390
        hir::ExprKind::Struct(..) => true,
2391

C
csmoe 已提交
2392 2393 2394
        hir::ExprKind::Assign(ref lhs, ref rhs) |
        hir::ExprKind::AssignOp(_, ref lhs, ref rhs) |
        hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
2395 2396 2397
            // X { y: 1 } + X { y: 2 }
            contains_exterior_struct_lit(&lhs) || contains_exterior_struct_lit(&rhs)
        }
C
csmoe 已提交
2398 2399 2400 2401 2402
        hir::ExprKind::Unary(_, ref x) |
        hir::ExprKind::Cast(ref x, _) |
        hir::ExprKind::Type(ref x, _) |
        hir::ExprKind::Field(ref x, _) |
        hir::ExprKind::Index(ref x, _) => {
2403 2404 2405 2406
            // &X { y: 1 }, X { y: 1 }.y
            contains_exterior_struct_lit(&x)
        }

C
csmoe 已提交
2407
        hir::ExprKind::MethodCall(.., ref exprs) => {
2408 2409 2410 2411 2412 2413 2414
            // X { y: 1 }.bar(...)
            contains_exterior_struct_lit(&exprs[0])
        }

        _ => false,
    }
}