rust/src/librustc/hir/print.rs

2362 lines
80 KiB
Rust
Raw Normal View History

2015-07-31 00:04:06 -07:00
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use self::AnnNode::*;
use syntax::abi::Abi;
2015-07-31 00:04:06 -07:00
use syntax::ast;
use syntax::codemap::{self, CodeMap, BytePos, Spanned};
use syntax::errors;
use syntax::parse::token::{self, keywords, BinOpToken};
2015-07-31 00:04:06 -07:00
use syntax::parse::lexer::comments;
use syntax::print::pp::{self, break_offset, word, space, hardbreak};
2015-07-31 00:04:06 -07:00
use syntax::print::pp::{Breaks, eof};
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
use syntax::print::pprust::{self as ast_pp, PrintState};
2015-07-31 00:04:06 -07:00
use syntax::ptr::P;
use hir;
2016-05-08 21:19:29 +03:00
use hir::{Crate, PatKind, RegionTyParamBound, SelfKind, TraitTyParamBound, TraitBoundModifier};
2015-07-31 00:04:06 -07:00
use std::io::{self, Write, Read};
pub enum AnnNode<'a> {
NodeName(&'a ast::Name),
NodeBlock(&'a hir::Block),
NodeItem(&'a hir::Item),
NodeSubItem(ast::NodeId),
NodeExpr(&'a hir::Expr),
NodePat(&'a hir::Pat),
}
pub trait PpAnn {
2015-09-28 08:23:31 +13:00
fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
Ok(())
}
fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
Ok(())
}
2015-07-31 00:04:06 -07:00
}
#[derive(Copy, Clone)]
pub struct NoAnn;
impl PpAnn for NoAnn {}
pub struct State<'a> {
krate: Option<&'a Crate>,
2015-07-31 00:04:06 -07:00
pub s: pp::Printer<'a>,
cm: Option<&'a CodeMap>,
comments: Option<Vec<comments::Comment>>,
literals: Option<Vec<comments::Literal>>,
cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral,
2015-07-31 00:04:06 -07:00
boxes: Vec<pp::Breaks>,
2015-09-28 08:23:31 +13:00
ann: &'a (PpAnn + 'a),
2015-07-31 00:04:06 -07:00
}
impl<'a> PrintState<'a> for State<'a> {
fn writer(&mut self) -> &mut pp::Printer<'a> {
&mut self.s
}
fn boxes(&mut self) -> &mut Vec<pp::Breaks> {
&mut self.boxes
}
fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> {
&mut self.comments
}
fn cur_cmnt_and_lit(&mut self) -> &mut ast_pp::CurrentCommentAndLiteral {
&mut self.cur_cmnt_and_lit
}
fn literals(&self) -> &Option<Vec<comments::Literal>> {
&self.literals
}
}
pub fn rust_printer<'a>(writer: Box<Write + 'a>, krate: Option<&'a Crate>) -> State<'a> {
2015-07-31 00:04:06 -07:00
static NO_ANN: NoAnn = NoAnn;
rust_printer_annotated(writer, &NO_ANN, krate)
2015-07-31 00:04:06 -07:00
}
2015-11-18 06:14:26 -05:00
pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>,
ann: &'a PpAnn,
krate: Option<&'a Crate>)
-> State<'a> {
2015-07-31 00:04:06 -07:00
State {
krate: krate,
2015-07-31 00:04:06 -07:00
s: pp::mk_printer(writer, default_columns),
cm: None,
comments: None,
literals: None,
cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
2015-07-31 00:04:06 -07:00
cur_cmnt: 0,
2015-09-28 08:23:31 +13:00
cur_lit: 0,
2015-07-31 00:04:06 -07:00
},
boxes: Vec::new(),
ann: ann,
}
}
#[allow(non_upper_case_globals)]
pub const indent_unit: usize = 4;
#[allow(non_upper_case_globals)]
pub const default_columns: usize = 78;
/// Requires you to pass an input filename and reader so that
/// it can scan the input text for comments and literals to
/// copy forward.
pub fn print_crate<'a>(cm: &'a CodeMap,
span_diagnostic: &errors::Handler,
2015-07-31 00:04:06 -07:00
krate: &hir::Crate,
filename: String,
input: &mut Read,
2015-09-28 08:23:31 +13:00
out: Box<Write + 'a>,
2015-07-31 00:04:06 -07:00
ann: &'a PpAnn,
2015-09-28 08:23:31 +13:00
is_expanded: bool)
-> io::Result<()> {
2015-11-18 06:14:26 -05:00
let mut s = State::new_from_input(cm, span_diagnostic, filename, input,
out, ann, is_expanded, Some(krate));
2015-07-31 00:04:06 -07:00
// When printing the AST, we sometimes need to inject `#[no_std]` here.
// Since you can't compile the HIR, it's not necessary.
s.print_mod(&krate.module, &krate.attrs)?;
s.print_remaining_comments()?;
2015-07-31 00:04:06 -07:00
eof(&mut s.s)
}
impl<'a> State<'a> {
pub fn new_from_input(cm: &'a CodeMap,
span_diagnostic: &errors::Handler,
2015-07-31 00:04:06 -07:00
filename: String,
input: &mut Read,
2015-09-28 08:23:31 +13:00
out: Box<Write + 'a>,
2015-07-31 00:04:06 -07:00
ann: &'a PpAnn,
is_expanded: bool,
krate: Option<&'a Crate>)
2015-09-28 08:23:31 +13:00
-> State<'a> {
let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic,
filename,
input);
State::new(cm,
out,
ann,
Some(cmnts),
// If the code is post expansion, don't use the table of
// literals, since it doesn't correspond with the literals
// in the AST anymore.
if is_expanded {
None
} else {
Some(lits)
},
krate)
2015-07-31 00:04:06 -07:00
}
pub fn new(cm: &'a CodeMap,
2015-09-28 08:23:31 +13:00
out: Box<Write + 'a>,
2015-07-31 00:04:06 -07:00
ann: &'a PpAnn,
comments: Option<Vec<comments::Comment>>,
literals: Option<Vec<comments::Literal>>,
krate: Option<&'a Crate>)
2015-09-28 08:23:31 +13:00
-> State<'a> {
2015-07-31 00:04:06 -07:00
State {
krate: krate,
2015-07-31 00:04:06 -07:00
s: pp::mk_printer(out, default_columns),
cm: Some(cm),
comments: comments.clone(),
literals: literals.clone(),
cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
2015-07-31 00:04:06 -07:00
cur_cmnt: 0,
2015-09-28 08:23:31 +13:00
cur_lit: 0,
2015-07-31 00:04:06 -07:00
},
boxes: Vec::new(),
ann: ann,
}
}
}
2015-09-28 08:23:31 +13:00
pub fn to_string<F>(f: F) -> String
where F: FnOnce(&mut State) -> io::Result<()>
2015-07-31 00:04:06 -07:00
{
let mut wr = Vec::new();
{
let mut printer = rust_printer(Box::new(&mut wr), None);
2015-07-31 00:04:06 -07:00
f(&mut printer).unwrap();
eof(&mut printer.s).unwrap();
}
String::from_utf8(wr).unwrap()
}
pub fn binop_to_string(op: BinOpToken) -> &'static str {
match op {
2015-09-28 08:23:31 +13:00
token::Plus => "+",
token::Minus => "-",
token::Star => "*",
token::Slash => "/",
token::Percent => "%",
token::Caret => "^",
token::And => "&",
token::Or => "|",
token::Shl => "<<",
token::Shr => ">>",
2015-07-31 00:04:06 -07:00
}
}
pub fn ty_to_string(ty: &hir::Ty) -> String {
to_string(|s| s.print_type(ty))
}
pub fn bounds_to_string(bounds: &[hir::TyParamBound]) -> String {
to_string(|s| s.print_bounds("", bounds))
}
pub fn pat_to_string(pat: &hir::Pat) -> String {
to_string(|s| s.print_pat(pat))
}
pub fn arm_to_string(arm: &hir::Arm) -> String {
to_string(|s| s.print_arm(arm))
}
pub fn expr_to_string(e: &hir::Expr) -> String {
to_string(|s| s.print_expr(e))
}
pub fn lifetime_to_string(e: &hir::Lifetime) -> String {
to_string(|s| s.print_lifetime(e))
}
pub fn stmt_to_string(stmt: &hir::Stmt) -> String {
to_string(|s| s.print_stmt(stmt))
}
pub fn item_to_string(i: &hir::Item) -> String {
to_string(|s| s.print_item(i))
}
pub fn impl_item_to_string(i: &hir::ImplItem) -> String {
to_string(|s| s.print_impl_item(i))
}
pub fn trait_item_to_string(i: &hir::TraitItem) -> String {
to_string(|s| s.print_trait_item(i))
}
pub fn generics_to_string(generics: &hir::Generics) -> String {
to_string(|s| s.print_generics(generics))
}
pub fn where_clause_to_string(i: &hir::WhereClause) -> String {
to_string(|s| s.print_where_clause(i))
}
pub fn fn_block_to_string(p: &hir::FnDecl) -> String {
to_string(|s| s.print_fn_block_args(p))
}
pub fn path_to_string(p: &hir::Path) -> String {
to_string(|s| s.print_path(p, false, 0))
}
pub fn name_to_string(name: ast::Name) -> String {
to_string(|s| s.print_name(name))
2015-07-31 00:04:06 -07:00
}
pub fn fun_to_string(decl: &hir::FnDecl,
unsafety: hir::Unsafety,
constness: hir::Constness,
2015-09-20 04:50:30 +03:00
name: ast::Name,
2015-07-31 00:04:06 -07:00
generics: &hir::Generics)
-> String {
to_string(|s| {
s.head("")?;
s.print_fn(decl,
2016-03-22 17:58:45 -05:00
unsafety,
constness,
Abi::Rust,
Some(name),
generics,
&hir::Inherited)?;
s.end()?; // Close the head box
2015-07-31 00:04:06 -07:00
s.end() // Close the outer box
})
}
pub fn block_to_string(blk: &hir::Block) -> String {
to_string(|s| {
// containing cbox, will be closed by print-block at }
s.cbox(indent_unit)?;
2015-07-31 00:04:06 -07:00
// head-ibox, will be closed by print-block after {
s.ibox(0)?;
2015-07-31 00:04:06 -07:00
s.print_block(blk)
})
}
pub fn variant_to_string(var: &hir::Variant) -> String {
to_string(|s| s.print_variant(var))
}
pub fn arg_to_string(arg: &hir::Arg) -> String {
to_string(|s| s.print_arg(arg, false))
2015-07-31 00:04:06 -07:00
}
pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String {
match *vis {
2015-07-31 00:04:06 -07:00
hir::Public => format!("pub {}", s),
hir::Visibility::Crate => format!("pub(crate) {}", s),
hir::Visibility::Restricted { ref path, .. } => format!("pub({}) {}", path, s),
2015-09-28 08:23:31 +13:00
hir::Inherited => s.to_string(),
2015-07-31 00:04:06 -07:00
}
}
fn needs_parentheses(expr: &hir::Expr) -> bool {
match expr.node {
2015-09-28 08:23:31 +13:00
hir::ExprAssign(..) |
hir::ExprBinary(..) |
2015-07-31 00:04:06 -07:00
hir::ExprClosure(..) |
2015-09-28 08:23:31 +13:00
hir::ExprAssignOp(..) |
hir::ExprCast(..) |
hir::ExprType(..) => true,
2015-07-31 00:04:06 -07:00
_ => false,
}
}
impl<'a> State<'a> {
pub fn cbox(&mut self, u: usize) -> io::Result<()> {
self.boxes.push(pp::Breaks::Consistent);
pp::cbox(&mut self.s, u)
}
2015-09-28 08:23:31 +13:00
pub fn nbsp(&mut self) -> io::Result<()> {
word(&mut self.s, " ")
}
2015-07-31 00:04:06 -07:00
pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
word(&mut self.s, w)?;
2015-07-31 00:04:06 -07:00
self.nbsp()
}
pub fn head(&mut self, w: &str) -> io::Result<()> {
// outer-box is consistent
self.cbox(indent_unit)?;
2015-07-31 00:04:06 -07:00
// head-box is inconsistent
self.ibox(w.len() + 1)?;
2015-07-31 00:04:06 -07:00
// keyword that starts the head
if !w.is_empty() {
self.word_nbsp(w)?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
pub fn bopen(&mut self) -> io::Result<()> {
word(&mut self.s, "{")?;
2015-07-31 00:04:06 -07:00
self.end() // close the head-box
}
2015-09-28 08:23:31 +13:00
pub fn bclose_(&mut self, span: codemap::Span, indented: usize) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
self.bclose_maybe_open(span, indented, true)
}
2015-09-28 08:23:31 +13:00
pub fn bclose_maybe_open(&mut self,
span: codemap::Span,
indented: usize,
close_box: bool)
-> io::Result<()> {
self.maybe_print_comment(span.hi)?;
self.break_offset_if_not_bol(1, -(indented as isize))?;
word(&mut self.s, "}")?;
2015-07-31 00:04:06 -07:00
if close_box {
self.end()?; // close the outer-box
2015-07-31 00:04:06 -07:00
}
Ok(())
}
pub fn bclose(&mut self, span: codemap::Span) -> io::Result<()> {
self.bclose_(span, indent_unit)
}
pub fn in_cbox(&self) -> bool {
match self.boxes.last() {
Some(&last_box) => last_box == pp::Breaks::Consistent,
2015-09-28 08:23:31 +13:00
None => false,
2015-07-31 00:04:06 -07:00
}
}
pub fn space_if_not_bol(&mut self) -> io::Result<()> {
2015-09-28 08:23:31 +13:00
if !self.is_bol() {
space(&mut self.s)?;
2015-09-28 08:23:31 +13:00
}
2015-07-31 00:04:06 -07:00
Ok(())
}
2015-09-28 08:23:31 +13:00
pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
if !self.is_bol() {
break_offset(&mut self.s, n, off)
} else {
if off != 0 && self.s.last_token().is_hardbreak_tok() {
// We do something pretty sketchy here: tuck the nonzero
// offset-adjustment we were going to deposit along with the
// break into the previous hardbreak.
self.s.replace_last_token(pp::hardbreak_tok_offset(off));
}
Ok(())
}
}
// Synthesizes a comment that was not textually present in the original source
// file.
pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
word(&mut self.s, "/*")?;
space(&mut self.s)?;
word(&mut self.s, &text[..])?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
word(&mut self.s, "*/")
}
pub fn commasep_cmnt<T, F, G>(&mut self,
b: Breaks,
elts: &[T],
mut op: F,
2015-09-28 08:23:31 +13:00
mut get_span: G)
-> io::Result<()>
where F: FnMut(&mut State, &T) -> io::Result<()>,
G: FnMut(&T) -> codemap::Span
2015-07-31 00:04:06 -07:00
{
self.rbox(0, b)?;
2015-07-31 00:04:06 -07:00
let len = elts.len();
let mut i = 0;
for elt in elts {
self.maybe_print_comment(get_span(elt).hi)?;
op(self, elt)?;
2015-07-31 00:04:06 -07:00
i += 1;
if i < len {
word(&mut self.s, ",")?;
self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi))?;
self.space_if_not_bol()?;
2015-07-31 00:04:06 -07:00
}
}
self.end()
}
2015-09-28 08:23:31 +13:00
pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<hir::Expr>]) -> io::Result<()> {
self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span)
2015-07-31 00:04:06 -07:00
}
2015-09-28 08:23:31 +13:00
pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
self.print_inner_attributes(attrs)?;
for item_id in &_mod.item_ids {
self.print_item_id(item_id)?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
2015-09-28 08:23:31 +13:00
pub fn print_foreign_mod(&mut self,
nmod: &hir::ForeignMod,
attrs: &[ast::Attribute])
-> io::Result<()> {
self.print_inner_attributes(attrs)?;
2015-07-31 00:04:06 -07:00
for item in &nmod.items {
self.print_foreign_item(item)?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
2015-09-28 08:23:31 +13:00
pub fn print_opt_lifetime(&mut self, lifetime: &Option<hir::Lifetime>) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
if let Some(l) = *lifetime {
self.print_lifetime(&l)?;
self.nbsp()?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
self.maybe_print_comment(ty.span.lo)?;
self.ibox(0)?;
2015-07-31 00:04:06 -07:00
match ty.node {
hir::TyVec(ref ty) => {
word(&mut self.s, "[")?;
self.print_type(&ty)?;
word(&mut self.s, "]")?;
2015-07-31 00:04:06 -07:00
}
hir::TyPtr(ref mt) => {
word(&mut self.s, "*")?;
2015-07-31 00:04:06 -07:00
match mt.mutbl {
hir::MutMutable => self.word_nbsp("mut")?,
hir::MutImmutable => self.word_nbsp("const")?,
2015-07-31 00:04:06 -07:00
}
self.print_type(&mt.ty)?;
2015-07-31 00:04:06 -07:00
}
hir::TyRptr(ref lifetime, ref mt) => {
word(&mut self.s, "&")?;
self.print_opt_lifetime(lifetime)?;
self.print_mt(mt)?;
2015-07-31 00:04:06 -07:00
}
hir::TyTup(ref elts) => {
self.popen()?;
self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty))?;
2015-07-31 00:04:06 -07:00
if elts.len() == 1 {
word(&mut self.s, ",")?;
2015-07-31 00:04:06 -07:00
}
self.pclose()?;
2015-07-31 00:04:06 -07:00
}
hir::TyBareFn(ref f) => {
let generics = hir::Generics {
lifetimes: f.lifetimes.clone(),
2015-12-19 04:20:11 +03:00
ty_params: hir::HirVec::new(),
2015-07-31 00:04:06 -07:00
where_clause: hir::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: hir::HirVec::new(),
2015-07-31 00:04:06 -07:00
},
};
2016-05-08 21:19:29 +03:00
self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics)?;
2015-07-31 00:04:06 -07:00
}
hir::TyPath(None, ref path) => {
self.print_path(path, false, 0)?;
2015-07-31 00:04:06 -07:00
}
hir::TyPath(Some(ref qself), ref path) => {
self.print_qpath(path, qself, false)?
2015-07-31 00:04:06 -07:00
}
hir::TyObjectSum(ref ty, ref bounds) => {
self.print_type(&ty)?;
self.print_bounds("+", &bounds[..])?;
2015-07-31 00:04:06 -07:00
}
hir::TyPolyTraitRef(ref bounds) => {
self.print_bounds("", &bounds[..])?;
2015-07-31 00:04:06 -07:00
}
hir::TyFixedLengthVec(ref ty, ref v) => {
word(&mut self.s, "[")?;
self.print_type(&ty)?;
word(&mut self.s, "; ")?;
self.print_expr(&v)?;
word(&mut self.s, "]")?;
2015-07-31 00:04:06 -07:00
}
hir::TyTypeof(ref e) => {
word(&mut self.s, "typeof(")?;
self.print_expr(&e)?;
word(&mut self.s, ")")?;
2015-07-31 00:04:06 -07:00
}
hir::TyInfer => {
word(&mut self.s, "_")?;
2015-07-31 00:04:06 -07:00
}
}
self.end()
}
2015-09-28 08:23:31 +13:00
pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()> {
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(item.span.lo)?;
self.print_outer_attributes(&item.attrs)?;
2015-07-31 00:04:06 -07:00
match item.node {
hir::ForeignItemFn(ref decl, ref generics) => {
self.head("")?;
self.print_fn(decl,
2016-03-22 17:58:45 -05:00
hir::Unsafety::Normal,
hir::Constness::NotConst,
Abi::Rust,
Some(item.name),
generics,
&item.vis)?;
self.end()?; // end head-ibox
word(&mut self.s, ";")?;
2015-07-31 00:04:06 -07:00
self.end() // end the outer fn box
}
hir::ForeignItemStatic(ref t, m) => {
self.head(&visibility_qualified(&item.vis, "static"))?;
2015-07-31 00:04:06 -07:00
if m {
self.word_space("mut")?;
2015-07-31 00:04:06 -07:00
}
self.print_name(item.name)?;
self.word_space(":")?;
self.print_type(&t)?;
word(&mut self.s, ";")?;
self.end()?; // end the head-ibox
2015-07-31 00:04:06 -07:00
self.end() // end the outer cbox
}
}
}
fn print_associated_const(&mut self,
2015-09-20 04:50:30 +03:00
name: ast::Name,
2015-07-31 00:04:06 -07:00
ty: &hir::Ty,
default: Option<&hir::Expr>,
vis: &hir::Visibility)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
word(&mut self.s, &visibility_qualified(vis, ""))?;
self.word_space("const")?;
self.print_name(name)?;
self.word_space(":")?;
self.print_type(ty)?;
2015-07-31 00:04:06 -07:00
if let Some(expr) = default {
space(&mut self.s)?;
self.word_space("=")?;
self.print_expr(expr)?;
2015-07-31 00:04:06 -07:00
}
word(&mut self.s, ";")
}
fn print_associated_type(&mut self,
2015-09-20 04:50:30 +03:00
name: ast::Name,
2015-07-31 00:04:06 -07:00
bounds: Option<&hir::TyParamBounds>,
ty: Option<&hir::Ty>)
-> io::Result<()> {
self.word_space("type")?;
self.print_name(name)?;
2015-07-31 00:04:06 -07:00
if let Some(bounds) = bounds {
self.print_bounds(":", bounds)?;
2015-07-31 00:04:06 -07:00
}
if let Some(ty) = ty {
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(ty)?;
2015-07-31 00:04:06 -07:00
}
word(&mut self.s, ";")
}
pub fn print_item_id(&mut self, item_id: &hir::ItemId) -> io::Result<()> {
if let Some(krate) = self.krate {
// skip nested items if krate context was not provided
let item = &krate.items[&item_id.id];
self.print_item(item)
} else {
Ok(())
}
}
2015-07-31 00:04:06 -07:00
/// Pretty-print an item
pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(item.span.lo)?;
self.print_outer_attributes(&item.attrs)?;
self.ann.pre(self, NodeItem(item))?;
2015-07-31 00:04:06 -07:00
match item.node {
hir::ItemExternCrate(ref optional_path) => {
self.head(&visibility_qualified(&item.vis, "extern crate"))?;
2015-07-31 00:04:06 -07:00
if let Some(p) = *optional_path {
let val = p.as_str();
if val.contains("-") {
self.print_string(&val, ast::StrStyle::Cooked)?;
2015-07-31 00:04:06 -07:00
} else {
self.print_name(p)?;
2015-07-31 00:04:06 -07:00
}
space(&mut self.s)?;
word(&mut self.s, "as")?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
}
self.print_name(item.name)?;
word(&mut self.s, ";")?;
self.end()?; // end inner head-block
self.end()?; // end outer head-block
2015-07-31 00:04:06 -07:00
}
hir::ItemUse(ref vp) => {
self.head(&visibility_qualified(&item.vis, "use"))?;
self.print_view_path(&vp)?;
word(&mut self.s, ";")?;
self.end()?; // end inner head-block
self.end()?; // end outer head-block
2015-07-31 00:04:06 -07:00
}
hir::ItemStatic(ref ty, m, ref expr) => {
self.head(&visibility_qualified(&item.vis, "static"))?;
2015-07-31 00:04:06 -07:00
if m == hir::MutMutable {
self.word_space("mut")?;
2015-07-31 00:04:06 -07:00
}
self.print_name(item.name)?;
self.word_space(":")?;
self.print_type(&ty)?;
space(&mut self.s)?;
self.end()?; // end the head-ibox
2015-07-31 00:04:06 -07:00
self.word_space("=")?;
self.print_expr(&expr)?;
word(&mut self.s, ";")?;
self.end()?; // end the outer cbox
2015-07-31 00:04:06 -07:00
}
hir::ItemConst(ref ty, ref expr) => {
self.head(&visibility_qualified(&item.vis, "const"))?;
self.print_name(item.name)?;
self.word_space(":")?;
self.print_type(&ty)?;
space(&mut self.s)?;
self.end()?; // end the head-ibox
self.word_space("=")?;
self.print_expr(&expr)?;
word(&mut self.s, ";")?;
self.end()?; // end the outer cbox
2015-07-31 00:04:06 -07:00
}
hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
self.head("")?;
self.print_fn(decl,
2016-03-22 17:58:45 -05:00
unsafety,
constness,
abi,
Some(item.name),
typarams,
&item.vis)?;
word(&mut self.s, " ")?;
self.print_block_with_attrs(&body, &item.attrs)?;
2015-07-31 00:04:06 -07:00
}
hir::ItemMod(ref _mod) => {
self.head(&visibility_qualified(&item.vis, "mod"))?;
self.print_name(item.name)?;
self.nbsp()?;
self.bopen()?;
self.print_mod(_mod, &item.attrs)?;
self.bclose(item.span)?;
2015-07-31 00:04:06 -07:00
}
hir::ItemForeignMod(ref nmod) => {
self.head("extern")?;
self.word_nbsp(&nmod.abi.to_string())?;
self.bopen()?;
self.print_foreign_mod(nmod, &item.attrs)?;
self.bclose(item.span)?;
2015-07-31 00:04:06 -07:00
}
hir::ItemTy(ref ty, ref params) => {
self.ibox(indent_unit)?;
self.ibox(0)?;
self.word_nbsp(&visibility_qualified(&item.vis, "type"))?;
self.print_name(item.name)?;
self.print_generics(params)?;
self.end()?; // end the inner ibox
self.print_where_clause(&params.where_clause)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&ty)?;
word(&mut self.s, ";")?;
self.end()?; // end the outer ibox
2015-07-31 00:04:06 -07:00
}
hir::ItemEnum(ref enum_definition, ref params) => {
self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?;
2015-07-31 00:04:06 -07:00
}
hir::ItemStruct(ref struct_def, ref generics) => {
self.head(&visibility_qualified(&item.vis, "struct"))?;
self.print_struct(struct_def, generics, item.name, item.span, true)?;
2015-07-31 00:04:06 -07:00
}
hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
self.head("")?;
self.print_visibility(&item.vis)?;
self.print_unsafety(unsafety)?;
self.word_nbsp("impl")?;
self.print_trait_ref(trait_ref)?;
space(&mut self.s)?;
self.word_space("for")?;
self.word_space("..")?;
self.bopen()?;
self.bclose(item.span)?;
2015-07-31 00:04:06 -07:00
}
hir::ItemImpl(unsafety,
polarity,
ref generics,
ref opt_trait,
ref ty,
ref impl_items) => {
self.head("")?;
self.print_visibility(&item.vis)?;
self.print_unsafety(unsafety)?;
self.word_nbsp("impl")?;
2015-07-31 00:04:06 -07:00
if generics.is_parameterized() {
self.print_generics(generics)?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
}
match polarity {
hir::ImplPolarity::Negative => {
word(&mut self.s, "!")?;
2015-09-28 08:23:31 +13:00
}
2015-07-31 00:04:06 -07:00
_ => {}
}
match opt_trait {
&Some(ref t) => {
self.print_trait_ref(t)?;
space(&mut self.s)?;
self.word_space("for")?;
2015-07-31 00:04:06 -07:00
}
&None => {}
}
self.print_type(&ty)?;
self.print_where_clause(&generics.where_clause)?;
2015-07-31 00:04:06 -07:00
space(&mut self.s)?;
self.bopen()?;
self.print_inner_attributes(&item.attrs)?;
2015-07-31 00:04:06 -07:00
for impl_item in impl_items {
self.print_impl_item(impl_item)?;
2015-07-31 00:04:06 -07:00
}
self.bclose(item.span)?;
2015-07-31 00:04:06 -07:00
}
hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => {
self.head("")?;
self.print_visibility(&item.vis)?;
self.print_unsafety(unsafety)?;
self.word_nbsp("trait")?;
self.print_name(item.name)?;
self.print_generics(generics)?;
2015-07-31 00:04:06 -07:00
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b {
space(&mut self.s)?;
self.word_space("for ?")?;
self.print_trait_ref(&ptr.trait_ref)?;
2015-07-31 00:04:06 -07:00
} else {
real_bounds.push(b.clone());
}
}
self.print_bounds(":", &real_bounds[..])?;
self.print_where_clause(&generics.where_clause)?;
word(&mut self.s, " ")?;
self.bopen()?;
2015-07-31 00:04:06 -07:00
for trait_item in trait_items {
self.print_trait_item(trait_item)?;
2015-07-31 00:04:06 -07:00
}
self.bclose(item.span)?;
2015-07-31 00:04:06 -07:00
}
}
self.ann.post(self, NodeItem(item))
}
fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
self.print_path(&t.path, false, 0)
}
fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> {
if !lifetimes.is_empty() {
word(&mut self.s, "for<")?;
2015-07-31 00:04:06 -07:00
let mut comma = false;
for lifetime_def in lifetimes {
if comma {
self.word_space(",")?
2015-07-31 00:04:06 -07:00
}
self.print_lifetime_def(lifetime_def)?;
2015-07-31 00:04:06 -07:00
comma = true;
}
word(&mut self.s, ">")?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> {
self.print_formal_lifetime_list(&t.bound_lifetimes)?;
2015-07-31 00:04:06 -07:00
self.print_trait_ref(&t.trait_ref)
}
2015-09-28 08:23:31 +13:00
pub fn print_enum_def(&mut self,
enum_definition: &hir::EnumDef,
generics: &hir::Generics,
name: ast::Name,
2015-07-31 00:04:06 -07:00
span: codemap::Span,
visibility: &hir::Visibility)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
self.head(&visibility_qualified(visibility, "enum"))?;
self.print_name(name)?;
self.print_generics(generics)?;
self.print_where_clause(&generics.where_clause)?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
self.print_variants(&enum_definition.variants, span)
}
pub fn print_variants(&mut self,
variants: &[hir::Variant],
2015-09-28 08:23:31 +13:00
span: codemap::Span)
-> io::Result<()> {
self.bopen()?;
2015-07-31 00:04:06 -07:00
for v in variants {
self.space_if_not_bol()?;
self.maybe_print_comment(v.span.lo)?;
self.print_outer_attributes(&v.node.attrs)?;
self.ibox(indent_unit)?;
self.print_variant(v)?;
word(&mut self.s, ",")?;
self.end()?;
self.maybe_print_trailing_comment(v.span, None)?;
2015-07-31 00:04:06 -07:00
}
self.bclose(span)
}
pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
match *vis {
2015-07-31 00:04:06 -07:00
hir::Public => self.word_nbsp("pub"),
hir::Visibility::Crate => self.word_nbsp("pub(crate)"),
hir::Visibility::Restricted { ref path, .. } =>
self.word_nbsp(&format!("pub({})", path)),
2015-09-28 08:23:31 +13:00
hir::Inherited => Ok(()),
2015-07-31 00:04:06 -07:00
}
}
pub fn print_struct(&mut self,
struct_def: &hir::VariantData,
2015-07-31 00:04:06 -07:00
generics: &hir::Generics,
2015-09-20 04:50:30 +03:00
name: ast::Name,
span: codemap::Span,
print_finalizer: bool)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
self.print_name(name)?;
self.print_generics(generics)?;
2015-10-08 23:45:46 +03:00
if !struct_def.is_struct() {
if struct_def.is_tuple() {
self.popen()?;
self.commasep(Inconsistent, struct_def.fields(), |s, field| {
s.print_visibility(&field.vis)?;
s.maybe_print_comment(field.span.lo)?;
s.print_type(&field.ty)
})?;
self.pclose()?;
2015-07-31 00:04:06 -07:00
}
self.print_where_clause(&generics.where_clause)?;
if print_finalizer {
word(&mut self.s, ";")?;
}
self.end()?;
2015-07-31 00:04:06 -07:00
self.end() // close the outer-box
} else {
self.print_where_clause(&generics.where_clause)?;
self.nbsp()?;
self.bopen()?;
self.hardbreak_if_not_bol()?;
2015-07-31 00:04:06 -07:00
2015-10-08 23:45:46 +03:00
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_name(field.name)?;
self.word_nbsp(":")?;
self.print_type(&field.ty)?;
word(&mut self.s, ",")?;
2015-07-31 00:04:06 -07:00
}
self.bclose(span)
}
}
pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
self.head("")?;
let generics = hir::Generics::empty();
self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
2015-07-31 00:04:06 -07:00
match v.node.disr_expr {
Some(ref d) => {
space(&mut self.s)?;
self.word_space("=")?;
self.print_expr(&d)
2015-07-31 00:04:06 -07:00
}
2015-09-28 08:23:31 +13:00
_ => Ok(()),
2015-07-31 00:04:06 -07:00
}
}
pub fn print_method_sig(&mut self,
2015-09-20 04:50:30 +03:00
name: ast::Name,
2015-07-31 00:04:06 -07:00
m: &hir::MethodSig,
vis: &hir::Visibility)
2015-07-31 00:04:06 -07:00
-> io::Result<()> {
self.print_fn(&m.decl,
m.unsafety,
m.constness,
m.abi,
2015-09-20 04:50:30 +03:00
Some(name),
2015-07-31 00:04:06 -07:00
&m.generics,
vis)
}
2015-09-28 08:23:31 +13:00
pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
self.ann.pre(self, NodeSubItem(ti.id))?;
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(ti.span.lo)?;
self.print_outer_attributes(&ti.attrs)?;
2015-07-31 00:04:06 -07:00
match ti.node {
hir::ConstTraitItem(ref ty, ref default) => {
self.print_associated_const(ti.name,
2016-03-22 17:58:45 -05:00
&ty,
default.as_ref().map(|expr| &**expr),
&hir::Inherited)?;
2015-07-31 00:04:06 -07:00
}
hir::MethodTraitItem(ref sig, ref body) => {
if body.is_some() {
self.head("")?;
2015-07-31 00:04:06 -07:00
}
self.print_method_sig(ti.name, sig, &hir::Inherited)?;
2015-07-31 00:04:06 -07:00
if let Some(ref body) = *body {
self.nbsp()?;
self.print_block_with_attrs(body, &ti.attrs)?;
2015-07-31 00:04:06 -07:00
} else {
word(&mut self.s, ";")?;
2015-07-31 00:04:06 -07:00
}
}
hir::TypeTraitItem(ref bounds, ref default) => {
self.print_associated_type(ti.name,
2016-03-22 17:58:45 -05:00
Some(bounds),
default.as_ref().map(|ty| &**ty))?;
2015-07-31 00:04:06 -07:00
}
}
self.ann.post(self, NodeSubItem(ti.id))
}
pub fn print_impl_item(&mut self, ii: &hir::ImplItem) -> io::Result<()> {
self.ann.pre(self, NodeSubItem(ii.id))?;
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(ii.span.lo)?;
self.print_outer_attributes(&ii.attrs)?;
if let hir::Defaultness::Default = ii.defaultness {
self.word_nbsp("default")?;
}
2015-07-31 00:04:06 -07:00
match ii.node {
2015-11-12 15:57:51 +01:00
hir::ImplItemKind::Const(ref ty, ref expr) => {
self.print_associated_const(ii.name, &ty, Some(&expr), &ii.vis)?;
2015-07-31 00:04:06 -07:00
}
2015-11-12 15:57:51 +01:00
hir::ImplItemKind::Method(ref sig, ref body) => {
self.head("")?;
self.print_method_sig(ii.name, sig, &ii.vis)?;
self.nbsp()?;
self.print_block_with_attrs(body, &ii.attrs)?;
2015-07-31 00:04:06 -07:00
}
2015-11-12 15:57:51 +01:00
hir::ImplItemKind::Type(ref ty) => {
self.print_associated_type(ii.name, None, Some(ty))?;
2015-07-31 00:04:06 -07:00
}
}
self.ann.post(self, NodeSubItem(ii.id))
}
pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
self.maybe_print_comment(st.span.lo)?;
2015-07-31 00:04:06 -07:00
match st.node {
hir::StmtDecl(ref decl, _) => {
self.print_decl(&decl)?;
2015-07-31 00:04:06 -07:00
}
hir::StmtExpr(ref expr, _) => {
self.space_if_not_bol()?;
self.print_expr(&expr)?;
2015-07-31 00:04:06 -07:00
}
hir::StmtSemi(ref expr, _) => {
self.space_if_not_bol()?;
self.print_expr(&expr)?;
word(&mut self.s, ";")?;
2015-07-31 00:04:06 -07:00
}
}
if stmt_ends_with_semi(&st.node) {
word(&mut self.s, ";")?;
2015-07-31 00:04:06 -07:00
}
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)
}
2015-09-28 08:23:31 +13:00
pub fn print_block_unclosed_indent(&mut self,
blk: &hir::Block,
indented: usize)
-> io::Result<()> {
2015-07-31 00:04:06 -07:00
self.print_block_maybe_unclosed(blk, indented, &[], false)
}
pub fn print_block_with_attrs(&mut self,
blk: &hir::Block,
2015-09-28 08:23:31 +13:00
attrs: &[ast::Attribute])
-> io::Result<()> {
2015-07-31 00:04:06 -07:00
self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
}
pub fn print_block_maybe_unclosed(&mut self,
blk: &hir::Block,
indented: usize,
attrs: &[ast::Attribute],
2015-09-28 08:23:31 +13:00
close_box: bool)
-> io::Result<()> {
2015-07-31 00:04:06 -07:00
match blk.rules {
hir::UnsafeBlock(..) => self.word_space("unsafe")?,
hir::PushUnsafeBlock(..) => self.word_space("push_unsafe")?,
hir::PopUnsafeBlock(..) => self.word_space("pop_unsafe")?,
hir::PushUnstableBlock => self.word_space("push_unstable")?,
hir::PopUnstableBlock => self.word_space("pop_unstable")?,
2015-09-29 13:46:01 +13:00
hir::DefaultBlock => (),
2015-07-31 00:04:06 -07:00
}
self.maybe_print_comment(blk.span.lo)?;
self.ann.pre(self, NodeBlock(blk))?;
self.bopen()?;
2015-07-31 00:04:06 -07:00
self.print_inner_attributes(attrs)?;
2015-07-31 00:04:06 -07:00
for st in &blk.stmts {
self.print_stmt(st)?;
2015-07-31 00:04:06 -07:00
}
match blk.expr {
Some(ref expr) => {
self.space_if_not_bol()?;
self.print_expr(&expr)?;
self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))?;
2015-07-31 00:04:06 -07:00
}
2015-09-28 08:23:31 +13:00
_ => (),
2015-07-31 00:04:06 -07:00
}
self.bclose_maybe_open(blk.span, indented, close_box)?;
2015-07-31 00:04:06 -07:00
self.ann.post(self, NodeBlock(blk))
}
fn print_else(&mut self, els: Option<&hir::Expr>) -> io::Result<()> {
match els {
Some(_else) => {
match _else.node {
// "another else-if"
hir::ExprIf(ref i, ref then, ref e) => {
self.cbox(indent_unit - 1)?;
self.ibox(0)?;
word(&mut self.s, " else if ")?;
self.print_expr(&i)?;
space(&mut self.s)?;
self.print_block(&then)?;
2015-07-31 00:04:06 -07:00
self.print_else(e.as_ref().map(|e| &**e))
}
// "final else"
hir::ExprBlock(ref b) => {
self.cbox(indent_unit - 1)?;
self.ibox(0)?;
word(&mut self.s, " else ")?;
self.print_block(&b)
2015-07-31 00:04:06 -07:00
}
// BLEAH, constraints would be great here
_ => {
panic!("print_if saw if with weird alternative");
}
}
}
2015-09-28 08:23:31 +13:00
_ => Ok(()),
2015-07-31 00:04:06 -07:00
}
}
2015-09-28 08:23:31 +13:00
pub fn print_if(&mut self,
test: &hir::Expr,
blk: &hir::Block,
elseopt: Option<&hir::Expr>)
-> io::Result<()> {
self.head("if")?;
self.print_expr(test)?;
space(&mut self.s)?;
self.print_block(blk)?;
2015-07-31 00:04:06 -07:00
self.print_else(elseopt)
}
2015-09-28 08:23:31 +13:00
pub fn print_if_let(&mut self,
pat: &hir::Pat,
expr: &hir::Expr,
blk: &hir::Block,
elseopt: Option<&hir::Expr>)
-> io::Result<()> {
self.head("if let")?;
self.print_pat(pat)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_expr(expr)?;
space(&mut self.s)?;
self.print_block(blk)?;
2015-07-31 00:04:06 -07:00
self.print_else(elseopt)
}
fn print_call_post(&mut self, args: &[P<hir::Expr>]) -> io::Result<()> {
self.popen()?;
self.commasep_exprs(Inconsistent, args)?;
2015-07-31 00:04:06 -07:00
self.pclose()
}
pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr) -> io::Result<()> {
let needs_par = needs_parentheses(expr);
if needs_par {
self.popen()?;
2015-07-31 00:04:06 -07:00
}
self.print_expr(expr)?;
2015-07-31 00:04:06 -07:00
if needs_par {
self.pclose()?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
fn print_expr_vec(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> {
self.ibox(indent_unit)?;
word(&mut self.s, "[")?;
self.commasep_exprs(Inconsistent, &exprs[..])?;
word(&mut self.s, "]")?;
2015-07-31 00:04:06 -07:00
self.end()
}
2015-09-28 08:23:31 +13:00
fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> {
self.ibox(indent_unit)?;
word(&mut self.s, "[")?;
self.print_expr(element)?;
self.word_space(";")?;
self.print_expr(count)?;
word(&mut self.s, "]")?;
2015-07-31 00:04:06 -07:00
self.end()
}
fn print_expr_struct(&mut self,
path: &hir::Path,
fields: &[hir::Field],
2015-09-28 08:23:31 +13:00
wth: &Option<P<hir::Expr>>)
-> io::Result<()> {
self.print_path(path, true, 0)?;
word(&mut self.s, "{")?;
self.commasep_cmnt(Consistent,
2016-03-22 17:58:45 -05:00
&fields[..],
|s, field| {
s.ibox(indent_unit)?;
s.print_name(field.name.node)?;
s.word_space(":")?;
s.print_expr(&field.expr)?;
s.end()
},
|f| f.span)?;
match *wth {
Some(ref expr) => {
self.ibox(indent_unit)?;
if !fields.is_empty() {
word(&mut self.s, ",")?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
}
word(&mut self.s, "..")?;
self.print_expr(&expr)?;
self.end()?;
}
_ => if !fields.is_empty() {
word(&mut self.s, ",")?
2015-09-28 08:23:31 +13:00
},
2015-07-31 00:04:06 -07:00
}
word(&mut self.s, "}")?;
2015-07-31 00:04:06 -07:00
Ok(())
}
fn print_expr_tup(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> {
self.popen()?;
self.commasep_exprs(Inconsistent, &exprs[..])?;
2015-07-31 00:04:06 -07:00
if exprs.len() == 1 {
word(&mut self.s, ",")?;
2015-07-31 00:04:06 -07:00
}
self.pclose()
}
2015-09-28 08:23:31 +13:00
fn print_expr_call(&mut self, func: &hir::Expr, args: &[P<hir::Expr>]) -> io::Result<()> {
self.print_expr_maybe_paren(func)?;
2015-07-31 00:04:06 -07:00
self.print_call_post(args)
}
fn print_expr_method_call(&mut self,
name: Spanned<ast::Name>,
2015-07-31 00:04:06 -07:00
tys: &[P<hir::Ty>],
2015-09-28 08:23:31 +13:00
args: &[P<hir::Expr>])
-> io::Result<()> {
2015-07-31 00:04:06 -07:00
let base_args = &args[1..];
self.print_expr(&args[0])?;
word(&mut self.s, ".")?;
self.print_name(name.node)?;
2015-07-31 00:04:06 -07:00
if !tys.is_empty() {
word(&mut self.s, "::<")?;
self.commasep(Inconsistent, tys, |s, ty| s.print_type(&ty))?;
word(&mut self.s, ">")?;
2015-07-31 00:04:06 -07:00
}
self.print_call_post(base_args)
}
fn print_expr_binary(&mut self,
op: hir::BinOp,
lhs: &hir::Expr,
2015-09-28 08:23:31 +13:00
rhs: &hir::Expr)
-> io::Result<()> {
self.print_expr(lhs)?;
space(&mut self.s)?;
self.word_space(op.node.as_str())?;
2015-07-31 00:04:06 -07:00
self.print_expr(rhs)
}
2015-09-28 08:23:31 +13:00
fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> {
word(&mut self.s, op.as_str())?;
2015-07-31 00:04:06 -07:00
self.print_expr_maybe_paren(expr)
}
fn print_expr_addr_of(&mut self,
mutability: hir::Mutability,
2015-09-28 08:23:31 +13:00
expr: &hir::Expr)
-> io::Result<()> {
word(&mut self.s, "&")?;
self.print_mutability(mutability)?;
2015-07-31 00:04:06 -07:00
self.print_expr_maybe_paren(expr)
}
pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
self.maybe_print_comment(expr.span.lo)?;
self.ibox(indent_unit)?;
self.ann.pre(self, NodeExpr(expr))?;
2015-07-31 00:04:06 -07:00
match expr.node {
hir::ExprBox(ref expr) => {
self.word_space("box")?;
self.print_expr(expr)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprVec(ref exprs) => {
self.print_expr_vec(&exprs[..])?;
2015-07-31 00:04:06 -07:00
}
hir::ExprRepeat(ref element, ref count) => {
self.print_expr_repeat(&element, &count)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprStruct(ref path, ref fields, ref wth) => {
self.print_expr_struct(path, &fields[..], wth)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprTup(ref exprs) => {
self.print_expr_tup(&exprs[..])?;
2015-07-31 00:04:06 -07:00
}
hir::ExprCall(ref func, ref args) => {
self.print_expr_call(&func, &args[..])?;
2015-07-31 00:04:06 -07:00
}
hir::ExprMethodCall(name, ref tys, ref args) => {
self.print_expr_method_call(name, &tys[..], &args[..])?;
2015-07-31 00:04:06 -07:00
}
hir::ExprBinary(op, ref lhs, ref rhs) => {
self.print_expr_binary(op, &lhs, &rhs)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprUnary(op, ref expr) => {
self.print_expr_unary(op, &expr)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprAddrOf(m, ref expr) => {
self.print_expr_addr_of(m, &expr)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprLit(ref lit) => {
self.print_literal(&lit)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprCast(ref expr, ref ty) => {
self.print_expr(&expr)?;
space(&mut self.s)?;
self.word_space("as")?;
self.print_type(&ty)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprType(ref expr, ref ty) => {
self.print_expr(&expr)?;
self.word_space(":")?;
self.print_type(&ty)?;
}
2015-07-31 00:04:06 -07:00
hir::ExprIf(ref test, ref blk, ref elseopt) => {
self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
2015-07-31 00:04:06 -07:00
}
2016-03-06 15:54:44 +03:00
hir::ExprWhile(ref test, ref blk, opt_name) => {
if let Some(name) = opt_name {
self.print_name(name)?;
self.word_space(":")?;
2015-07-31 00:04:06 -07:00
}
self.head("while")?;
self.print_expr(&test)?;
space(&mut self.s)?;
self.print_block(&blk)?;
2015-07-31 00:04:06 -07:00
}
2016-03-06 15:54:44 +03:00
hir::ExprLoop(ref blk, opt_name) => {
if let Some(name) = opt_name {
self.print_name(name)?;
self.word_space(":")?;
2015-07-31 00:04:06 -07:00
}
self.head("loop")?;
space(&mut self.s)?;
self.print_block(&blk)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprMatch(ref expr, ref arms, _) => {
self.cbox(indent_unit)?;
self.ibox(4)?;
self.word_nbsp("match")?;
self.print_expr(&expr)?;
space(&mut self.s)?;
self.bopen()?;
2015-07-31 00:04:06 -07:00
for arm in arms {
self.print_arm(arm)?;
2015-07-31 00:04:06 -07:00
}
self.bclose_(expr.span, indent_unit)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprClosure(capture_clause, ref decl, ref body, _fn_decl_span) => {
self.print_capture_clause(capture_clause)?;
2015-07-31 00:04:06 -07:00
self.print_fn_block_args(&decl)?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
let default_return = match decl.output {
hir::DefaultReturn(..) => true,
2015-09-28 08:23:31 +13:00
_ => false,
2015-07-31 00:04:06 -07:00
};
if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
self.print_block_unclosed(&body)?;
2015-07-31 00:04:06 -07:00
} else {
// we extract the block, so as not to create another set of boxes
match body.expr.as_ref().unwrap().node {
hir::ExprBlock(ref blk) => {
self.print_block_unclosed(&blk)?;
2015-07-31 00:04:06 -07:00
}
_ => {
// this is a bare expression
self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())?;
self.end()?; // need to close a box
2015-07-31 00:04:06 -07:00
}
}
}
// 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.
self.ibox(0)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprBlock(ref blk) => {
// containing cbox, will be closed by print-block at }
self.cbox(indent_unit)?;
2015-07-31 00:04:06 -07:00
// head-box, will be closed by print-block after {
self.ibox(0)?;
self.print_block(&blk)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprAssign(ref lhs, ref rhs) => {
self.print_expr(&lhs)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_expr(&rhs)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
self.print_expr(&lhs)?;
space(&mut self.s)?;
word(&mut self.s, op.node.as_str())?;
self.word_space("=")?;
self.print_expr(&rhs)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprField(ref expr, name) => {
self.print_expr(&expr)?;
word(&mut self.s, ".")?;
self.print_name(name.node)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprTupField(ref expr, id) => {
self.print_expr(&expr)?;
word(&mut self.s, ".")?;
self.print_usize(id.node)?;
2015-07-31 00:04:06 -07:00
}
hir::ExprIndex(ref expr, ref index) => {
self.print_expr(&expr)?;
word(&mut self.s, "[")?;
self.print_expr(&index)?;
word(&mut self.s, "]")?;
2015-07-31 00:04:06 -07:00
}
hir::ExprPath(None, ref path) => {
self.print_path(path, true, 0)?
2015-07-31 00:04:06 -07:00
}
hir::ExprPath(Some(ref qself), ref path) => {
self.print_qpath(path, qself, true)?
2015-07-31 00:04:06 -07:00
}
2016-03-06 15:54:44 +03:00
hir::ExprBreak(opt_name) => {
word(&mut self.s, "break")?;
space(&mut self.s)?;
2016-03-06 15:54:44 +03:00
if let Some(name) = opt_name {
self.print_name(name.node)?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
}
}
2016-03-06 15:54:44 +03:00
hir::ExprAgain(opt_name) => {
word(&mut self.s, "continue")?;
space(&mut self.s)?;
2016-03-06 15:54:44 +03:00
if let Some(name) = opt_name {
self.print_name(name.node)?;
space(&mut self.s)?
2015-07-31 00:04:06 -07:00
}
}
hir::ExprRet(ref result) => {
word(&mut self.s, "return")?;
2015-07-31 00:04:06 -07:00
match *result {
Some(ref expr) => {
word(&mut self.s, " ")?;
self.print_expr(&expr)?;
2015-07-31 00:04:06 -07:00
}
2015-09-28 08:23:31 +13:00
_ => (),
2015-07-31 00:04:06 -07:00
}
}
hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => {
word(&mut self.s, "asm!")?;
self.popen()?;
self.print_string(&a.asm, a.asm_str_style)?;
self.word_space(":")?;
2015-07-31 00:04:06 -07:00
let mut out_idx = 0;
self.commasep(Inconsistent, &a.outputs, |s, out| {
std: Stabilize APIs for the 1.9 release This commit applies all stabilizations, renamings, and deprecations that the library team has decided on for the upcoming 1.9 release. All tracking issues have gone through a cycle-long "final comment period" and the specific APIs stabilized/deprecated are: Stable * `std::panic` * `std::panic::catch_unwind` (renamed from `recover`) * `std::panic::resume_unwind` (renamed from `propagate`) * `std::panic::AssertUnwindSafe` (renamed from `AssertRecoverSafe`) * `std::panic::UnwindSafe` (renamed from `RecoverSafe`) * `str::is_char_boundary` * `<*const T>::as_ref` * `<*mut T>::as_ref` * `<*mut T>::as_mut` * `AsciiExt::make_ascii_uppercase` * `AsciiExt::make_ascii_lowercase` * `char::decode_utf16` * `char::DecodeUtf16` * `char::DecodeUtf16Error` * `char::DecodeUtf16Error::unpaired_surrogate` * `BTreeSet::take` * `BTreeSet::replace` * `BTreeSet::get` * `HashSet::take` * `HashSet::replace` * `HashSet::get` * `OsString::with_capacity` * `OsString::clear` * `OsString::capacity` * `OsString::reserve` * `OsString::reserve_exact` * `OsStr::is_empty` * `OsStr::len` * `std::os::unix::thread` * `RawPthread` * `JoinHandleExt` * `JoinHandleExt::as_pthread_t` * `JoinHandleExt::into_pthread_t` * `HashSet::hasher` * `HashMap::hasher` * `CommandExt::exec` * `File::try_clone` * `SocketAddr::set_ip` * `SocketAddr::set_port` * `SocketAddrV4::set_ip` * `SocketAddrV4::set_port` * `SocketAddrV6::set_ip` * `SocketAddrV6::set_port` * `SocketAddrV6::set_flowinfo` * `SocketAddrV6::set_scope_id` * `<[T]>::copy_from_slice` * `ptr::read_volatile` * `ptr::write_volatile` * The `#[deprecated]` attribute * `OpenOptions::create_new` Deprecated * `std::raw::Slice` - use raw parts of `slice` module instead * `std::raw::Repr` - use raw parts of `slice` module instead * `str::char_range_at` - use slicing plus `chars()` plus `len_utf8` * `str::char_range_at_reverse` - use slicing plus `chars().rev()` plus `len_utf8` * `str::char_at` - use slicing plus `chars()` * `str::char_at_reverse` - use slicing plus `chars().rev()` * `str::slice_shift_char` - use `chars()` plus `Chars::as_str` * `CommandExt::session_leader` - use `before_exec` instead. Closes #27719 cc #27751 (deprecating the `Slice` bits) Closes #27754 Closes #27780 Closes #27809 Closes #27811 Closes #27830 Closes #28050 Closes #29453 Closes #29791 Closes #29935 Closes #30014 Closes #30752 Closes #31262 cc #31398 (still need to deal with `before_exec`) Closes #31405 Closes #31572 Closes #31755 Closes #31756
2016-04-07 10:42:53 -07:00
let mut ch = out.constraint.chars();
match ch.next() {
Some('=') if out.is_rw => {
s.print_string(&format!("+{}", ch.as_str()),
ast::StrStyle::Cooked)?
2015-11-05 21:17:59 +00:00
}
std: Stabilize APIs for the 1.9 release This commit applies all stabilizations, renamings, and deprecations that the library team has decided on for the upcoming 1.9 release. All tracking issues have gone through a cycle-long "final comment period" and the specific APIs stabilized/deprecated are: Stable * `std::panic` * `std::panic::catch_unwind` (renamed from `recover`) * `std::panic::resume_unwind` (renamed from `propagate`) * `std::panic::AssertUnwindSafe` (renamed from `AssertRecoverSafe`) * `std::panic::UnwindSafe` (renamed from `RecoverSafe`) * `str::is_char_boundary` * `<*const T>::as_ref` * `<*mut T>::as_ref` * `<*mut T>::as_mut` * `AsciiExt::make_ascii_uppercase` * `AsciiExt::make_ascii_lowercase` * `char::decode_utf16` * `char::DecodeUtf16` * `char::DecodeUtf16Error` * `char::DecodeUtf16Error::unpaired_surrogate` * `BTreeSet::take` * `BTreeSet::replace` * `BTreeSet::get` * `HashSet::take` * `HashSet::replace` * `HashSet::get` * `OsString::with_capacity` * `OsString::clear` * `OsString::capacity` * `OsString::reserve` * `OsString::reserve_exact` * `OsStr::is_empty` * `OsStr::len` * `std::os::unix::thread` * `RawPthread` * `JoinHandleExt` * `JoinHandleExt::as_pthread_t` * `JoinHandleExt::into_pthread_t` * `HashSet::hasher` * `HashMap::hasher` * `CommandExt::exec` * `File::try_clone` * `SocketAddr::set_ip` * `SocketAddr::set_port` * `SocketAddrV4::set_ip` * `SocketAddrV4::set_port` * `SocketAddrV6::set_ip` * `SocketAddrV6::set_port` * `SocketAddrV6::set_flowinfo` * `SocketAddrV6::set_scope_id` * `<[T]>::copy_from_slice` * `ptr::read_volatile` * `ptr::write_volatile` * The `#[deprecated]` attribute * `OpenOptions::create_new` Deprecated * `std::raw::Slice` - use raw parts of `slice` module instead * `std::raw::Repr` - use raw parts of `slice` module instead * `str::char_range_at` - use slicing plus `chars()` plus `len_utf8` * `str::char_range_at_reverse` - use slicing plus `chars().rev()` plus `len_utf8` * `str::char_at` - use slicing plus `chars()` * `str::char_at_reverse` - use slicing plus `chars().rev()` * `str::slice_shift_char` - use `chars()` plus `Chars::as_str` * `CommandExt::session_leader` - use `before_exec` instead. Closes #27719 cc #27751 (deprecating the `Slice` bits) Closes #27754 Closes #27780 Closes #27809 Closes #27811 Closes #27830 Closes #28050 Closes #29453 Closes #29791 Closes #29935 Closes #30014 Closes #30752 Closes #31262 cc #31398 (still need to deal with `before_exec`) Closes #31405 Closes #31572 Closes #31755 Closes #31756
2016-04-07 10:42:53 -07:00
_ => s.print_string(&out.constraint,
ast::StrStyle::Cooked)?,
2015-11-05 21:17:59 +00:00
}
s.popen()?;
s.print_expr(&outputs[out_idx])?;
s.pclose()?;
out_idx += 1;
2015-11-05 21:17:59 +00:00
Ok(())
})?;
space(&mut self.s)?;
self.word_space(":")?;
2015-07-31 00:04:06 -07:00
let mut in_idx = 0;
self.commasep(Inconsistent, &a.inputs, |s, co| {
s.print_string(&co, ast::StrStyle::Cooked)?;
s.popen()?;
s.print_expr(&inputs[in_idx])?;
s.pclose()?;
in_idx += 1;
2015-11-05 21:17:59 +00:00
Ok(())
})?;
space(&mut self.s)?;
self.word_space(":")?;
2015-07-31 00:04:06 -07:00
self.commasep(Inconsistent, &a.clobbers, |s, co| {
s.print_string(&co, ast::StrStyle::Cooked)?;
2015-11-05 21:17:59 +00:00
Ok(())
})?;
2015-07-31 00:04:06 -07:00
2015-11-05 21:17:59 +00:00
let mut options = vec![];
2015-07-31 00:04:06 -07:00
if a.volatile {
options.push("volatile");
}
if a.alignstack {
options.push("alignstack");
}
if a.dialect == ast::AsmDialect::Intel {
2015-07-31 00:04:06 -07:00
options.push("intel");
}
if !options.is_empty() {
space(&mut self.s)?;
self.word_space(":")?;
self.commasep(Inconsistent, &options, |s, &co| {
s.print_string(co, ast::StrStyle::Cooked)?;
2015-11-05 21:17:59 +00:00
Ok(())
})?;
2015-07-31 00:04:06 -07:00
}
self.pclose()?;
2015-07-31 00:04:06 -07:00
}
}
self.ann.post(self, NodeExpr(expr))?;
2015-07-31 00:04:06 -07:00
self.end()
}
pub fn print_local_decl(&mut self, loc: &hir::Local) -> io::Result<()> {
self.print_pat(&loc.pat)?;
2015-07-31 00:04:06 -07:00
if let Some(ref ty) = loc.ty {
self.word_space(":")?;
self.print_type(&ty)?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
self.maybe_print_comment(decl.span.lo)?;
2015-07-31 00:04:06 -07:00
match decl.node {
hir::DeclLocal(ref loc) => {
self.space_if_not_bol()?;
self.ibox(indent_unit)?;
self.word_nbsp("let")?;
2015-07-31 00:04:06 -07:00
self.ibox(indent_unit)?;
self.print_local_decl(&loc)?;
self.end()?;
2015-07-31 00:04:06 -07:00
if let Some(ref init) = loc.init {
self.nbsp()?;
self.word_space("=")?;
self.print_expr(&init)?;
2015-07-31 00:04:06 -07:00
}
self.end()
}
hir::DeclItem(ref item) => {
self.print_item_id(item)
}
2015-07-31 00:04:06 -07:00
}
}
pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
word(&mut self.s, &i.to_string())
}
pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
word(&mut self.s, &name.as_str())?;
2015-07-31 00:04:06 -07:00
self.ann.post(self, NodeName(&name))
}
2015-09-28 08:23:31 +13:00
pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> {
self.print_local_decl(loc)?;
space(&mut self.s)?;
self.word_space("in")?;
2015-07-31 00:04:06 -07:00
self.print_expr(coll)
}
fn print_path(&mut self,
path: &hir::Path,
colons_before_params: bool,
depth: usize)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
self.maybe_print_comment(path.span.lo)?;
2015-07-31 00:04:06 -07:00
let mut first = !path.global;
2015-11-05 21:17:59 +00:00
for segment in &path.segments[..path.segments.len() - depth] {
2015-07-31 00:04:06 -07:00
if first {
first = false
} else {
word(&mut self.s, "::")?
2015-07-31 00:04:06 -07:00
}
2016-03-06 15:54:44 +03:00
self.print_name(segment.name)?;
2015-07-31 00:04:06 -07:00
self.print_path_parameters(&segment.parameters, colons_before_params)?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
fn print_qpath(&mut self,
path: &hir::Path,
qself: &hir::QSelf,
colons_before_params: bool)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
word(&mut self.s, "<")?;
self.print_type(&qself.ty)?;
2015-07-31 00:04:06 -07:00
if qself.position > 0 {
space(&mut self.s)?;
self.word_space("as")?;
2015-07-31 00:04:06 -07:00
let depth = path.segments.len() - qself.position;
self.print_path(&path, false, depth)?;
2015-07-31 00:04:06 -07:00
}
word(&mut self.s, ">")?;
word(&mut self.s, "::")?;
2015-07-31 00:04:06 -07:00
let item_segment = path.segments.last().unwrap();
2016-03-06 15:54:44 +03:00
self.print_name(item_segment.name)?;
2015-07-31 00:04:06 -07:00
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
fn print_path_parameters(&mut self,
parameters: &hir::PathParameters,
colons_before_params: bool)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
2015-07-31 00:04:06 -07:00
if parameters.is_empty() {
return Ok(());
}
if colons_before_params {
word(&mut self.s, "::")?
2015-07-31 00:04:06 -07:00
}
match *parameters {
hir::AngleBracketedParameters(ref data) => {
word(&mut self.s, "<")?;
2015-07-31 00:04:06 -07:00
let mut comma = false;
for lifetime in &data.lifetimes {
if comma {
self.word_space(",")?
2015-07-31 00:04:06 -07:00
}
self.print_lifetime(lifetime)?;
2015-07-31 00:04:06 -07:00
comma = true;
}
if !data.types.is_empty() {
if comma {
self.word_space(",")?
2015-07-31 00:04:06 -07:00
}
self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?;
2015-09-28 08:23:31 +13:00
comma = true;
2015-07-31 00:04:06 -07:00
}
for binding in data.bindings.iter() {
if comma {
self.word_space(",")?
2015-07-31 00:04:06 -07:00
}
self.print_name(binding.name)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&binding.ty)?;
2015-07-31 00:04:06 -07:00
comma = true;
}
word(&mut self.s, ">")?
2015-07-31 00:04:06 -07:00
}
hir::ParenthesizedParameters(ref data) => {
word(&mut self.s, "(")?;
self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?;
word(&mut self.s, ")")?;
2015-07-31 00:04:06 -07:00
match data.output {
2015-09-28 08:23:31 +13:00
None => {}
2015-07-31 00:04:06 -07:00
Some(ref ty) => {
self.space_if_not_bol()?;
self.word_space("->")?;
self.print_type(&ty)?;
2015-07-31 00:04:06 -07:00
}
}
}
}
Ok(())
}
pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
self.maybe_print_comment(pat.span.lo)?;
self.ann.pre(self, NodePat(pat))?;
2015-11-05 21:17:59 +00:00
// Pat isn't normalized, but the beauty of it
// is that it doesn't matter
2015-07-31 00:04:06 -07:00
match pat.node {
PatKind::Wild => word(&mut self.s, "_")?,
2016-02-14 15:25:12 +03:00
PatKind::Ident(binding_mode, ref path1, ref sub) => {
2015-07-31 00:04:06 -07:00
match binding_mode {
hir::BindByRef(mutbl) => {
self.word_nbsp("ref")?;
self.print_mutability(mutbl)?;
2015-07-31 00:04:06 -07:00
}
hir::BindByValue(hir::MutImmutable) => {}
hir::BindByValue(hir::MutMutable) => {
self.word_nbsp("mut")?;
2015-07-31 00:04:06 -07:00
}
}
2016-03-06 15:54:44 +03:00
self.print_name(path1.node)?;
2015-07-31 00:04:06 -07:00
match *sub {
Some(ref p) => {
word(&mut self.s, "@")?;
self.print_pat(&p)?;
2015-07-31 00:04:06 -07:00
}
2015-09-28 08:23:31 +13:00
None => (),
2015-07-31 00:04:06 -07:00
}
}
PatKind::TupleStruct(ref path, ref args_) => {
self.print_path(path, true, 0)?;
2015-07-31 00:04:06 -07:00
match *args_ {
None => word(&mut self.s, "(..)")?,
2015-07-31 00:04:06 -07:00
Some(ref args) => {
self.popen()?;
self.commasep(Inconsistent, &args[..], |s, p| s.print_pat(&p))?;
self.pclose()?;
2015-07-31 00:04:06 -07:00
}
}
}
PatKind::Path(ref path) => {
self.print_path(path, true, 0)?;
}
2016-02-14 15:25:12 +03:00
PatKind::QPath(ref qself, ref path) => {
self.print_qpath(path, qself, false)?;
2015-07-31 00:04:06 -07:00
}
2016-02-14 15:25:12 +03:00
PatKind::Struct(ref path, ref fields, etc) => {
self.print_path(path, true, 0)?;
self.nbsp()?;
self.word_space("{")?;
self.commasep_cmnt(Consistent,
2016-03-22 17:58:45 -05:00
&fields[..],
|s, f| {
s.cbox(indent_unit)?;
if !f.node.is_shorthand {
s.print_name(f.node.name)?;
s.word_nbsp(":")?;
}
s.print_pat(&f.node.pat)?;
s.end()
},
|f| f.node.pat.span)?;
2015-07-31 00:04:06 -07:00
if etc {
2015-09-28 08:23:31 +13:00
if !fields.is_empty() {
self.word_space(",")?;
2015-09-28 08:23:31 +13:00
}
word(&mut self.s, "..")?;
2015-07-31 00:04:06 -07:00
}
space(&mut self.s)?;
word(&mut self.s, "}")?;
2015-07-31 00:04:06 -07:00
}
2016-02-14 15:25:12 +03:00
PatKind::Tup(ref elts) => {
self.popen()?;
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
2015-07-31 00:04:06 -07:00
if elts.len() == 1 {
word(&mut self.s, ",")?;
2015-07-31 00:04:06 -07:00
}
self.pclose()?;
2015-07-31 00:04:06 -07:00
}
2016-02-14 15:25:12 +03:00
PatKind::Box(ref inner) => {
word(&mut self.s, "box ")?;
self.print_pat(&inner)?;
2015-07-31 00:04:06 -07:00
}
2016-02-14 15:25:12 +03:00
PatKind::Ref(ref inner, mutbl) => {
word(&mut self.s, "&")?;
2015-07-31 00:04:06 -07:00
if mutbl == hir::MutMutable {
word(&mut self.s, "mut ")?;
2015-07-31 00:04:06 -07:00
}
self.print_pat(&inner)?;
2015-07-31 00:04:06 -07:00
}
PatKind::Lit(ref e) => self.print_expr(&e)?,
2016-02-14 15:25:12 +03:00
PatKind::Range(ref begin, ref end) => {
self.print_expr(&begin)?;
space(&mut self.s)?;
word(&mut self.s, "...")?;
self.print_expr(&end)?;
2015-07-31 00:04:06 -07:00
}
2016-02-14 15:25:12 +03:00
PatKind::Vec(ref before, ref slice, ref after) => {
word(&mut self.s, "[")?;
self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p))?;
2015-07-31 00:04:06 -07:00
if let Some(ref p) = *slice {
2015-09-28 08:23:31 +13:00
if !before.is_empty() {
self.word_space(",")?;
2015-09-28 08:23:31 +13:00
}
2016-02-14 15:25:12 +03:00
if p.node != PatKind::Wild {
self.print_pat(&p)?;
2015-07-31 00:04:06 -07:00
}
word(&mut self.s, "..")?;
2015-09-28 08:23:31 +13:00
if !after.is_empty() {
self.word_space(",")?;
2015-09-28 08:23:31 +13:00
}
2015-07-31 00:04:06 -07:00
}
self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p))?;
word(&mut self.s, "]")?;
2015-07-31 00:04:06 -07:00
}
}
self.ann.post(self, NodePat(pat))
}
fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> {
// I have no idea why this check is necessary, but here it
// is :(
if arm.attrs.is_empty() {
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
}
self.cbox(indent_unit)?;
self.ibox(0)?;
self.print_outer_attributes(&arm.attrs)?;
2015-07-31 00:04:06 -07:00
let mut first = true;
for p in &arm.pats {
if first {
first = false;
} else {
space(&mut self.s)?;
self.word_space("|")?;
2015-07-31 00:04:06 -07:00
}
self.print_pat(&p)?;
2015-07-31 00:04:06 -07:00
}
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
if let Some(ref e) = arm.guard {
self.word_space("if")?;
self.print_expr(&e)?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
}
self.word_space("=>")?;
2015-07-31 00:04:06 -07:00
match arm.body.node {
hir::ExprBlock(ref blk) => {
// the block will close the pattern's ibox
self.print_block_unclosed_indent(&blk, indent_unit)?;
2015-07-31 00:04:06 -07:00
// If it is a user-provided unsafe block, print a comma after it
if let hir::UnsafeBlock(hir::UserProvided) = blk.rules {
word(&mut self.s, ",")?;
2015-07-31 00:04:06 -07:00
}
}
_ => {
self.end()?; // close the ibox for the pattern
self.print_expr(&arm.body)?;
word(&mut self.s, ",")?;
2015-07-31 00:04:06 -07:00
}
}
self.end() // close enclosing cbox
}
2016-05-08 21:19:29 +03:00
fn print_explicit_self(&mut self, explicit_self: &hir::ExplicitSelf) -> io::Result<()> {
match explicit_self.node {
SelfKind::Value(m) => {
self.print_mutability(m)?;
word(&mut self.s, "self")
2015-07-31 00:04:06 -07:00
}
2016-05-08 21:19:29 +03:00
SelfKind::Region(ref lt, m) => {
word(&mut self.s, "&")?;
self.print_opt_lifetime(lt)?;
self.print_mutability(m)?;
2016-05-08 21:19:29 +03:00
word(&mut self.s, "self")
2015-07-31 00:04:06 -07:00
}
2016-05-08 21:19:29 +03:00
SelfKind::Explicit(ref typ, m) => {
self.print_mutability(m)?;
word(&mut self.s, "self")?;
self.word_space(":")?;
2016-05-08 21:19:29 +03:00
self.print_type(&typ)
2015-07-31 00:04:06 -07:00
}
}
}
pub fn print_fn(&mut self,
decl: &hir::FnDecl,
unsafety: hir::Unsafety,
constness: hir::Constness,
abi: Abi,
2015-09-20 04:50:30 +03:00
name: Option<ast::Name>,
2015-07-31 00:04:06 -07:00
generics: &hir::Generics,
vis: &hir::Visibility)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
self.print_fn_header_info(unsafety, constness, abi, vis)?;
2015-07-31 00:04:06 -07:00
if let Some(name) = name {
self.nbsp()?;
self.print_name(name)?;
2015-07-31 00:04:06 -07:00
}
self.print_generics(generics)?;
2016-05-08 21:19:29 +03:00
self.print_fn_args_and_ret(decl)?;
2015-07-31 00:04:06 -07:00
self.print_where_clause(&generics.where_clause)
}
2016-05-08 21:19:29 +03:00
pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
self.popen()?;
2016-05-08 21:19:29 +03:00
self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
2015-07-31 00:04:06 -07:00
if decl.variadic {
word(&mut self.s, ", ...")?;
2015-07-31 00:04:06 -07:00
}
self.pclose()?;
2015-07-31 00:04:06 -07:00
self.print_fn_output(decl)
}
2015-09-28 08:23:31 +13:00
pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
word(&mut self.s, "|")?;
2016-05-08 21:19:29 +03:00
self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?;
word(&mut self.s, "|")?;
2015-07-31 00:04:06 -07:00
if let hir::DefaultReturn(..) = decl.output {
return Ok(());
}
self.space_if_not_bol()?;
self.word_space("->")?;
2015-07-31 00:04:06 -07:00
match decl.output {
hir::Return(ref ty) => {
self.print_type(&ty)?;
2015-07-31 00:04:06 -07:00
self.maybe_print_comment(ty.span.lo)
}
hir::DefaultReturn(..) => unreachable!(),
hir::NoReturn(span) => {
self.word_nbsp("!")?;
2015-07-31 00:04:06 -07:00
self.maybe_print_comment(span.lo)
}
}
}
2015-09-28 08:23:31 +13:00
pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
match capture_clause {
hir::CaptureByValue => self.word_space("move"),
hir::CaptureByRef => Ok(()),
}
}
2015-09-28 08:23:31 +13:00
pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
if !bounds.is_empty() {
word(&mut self.s, prefix)?;
2015-07-31 00:04:06 -07:00
let mut first = true;
for bound in bounds {
self.nbsp()?;
2015-07-31 00:04:06 -07:00
if first {
first = false;
} else {
self.word_space("+")?;
2015-07-31 00:04:06 -07:00
}
match *bound {
2015-07-31 00:04:06 -07:00
TraitTyParamBound(ref tref, TraitBoundModifier::None) => {
self.print_poly_trait_ref(tref)
}
TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => {
word(&mut self.s, "?")?;
2015-07-31 00:04:06 -07:00
self.print_poly_trait_ref(tref)
}
RegionTyParamBound(ref lt) => {
self.print_lifetime(lt)
}
}?
2015-07-31 00:04:06 -07:00
}
Ok(())
} else {
Ok(())
}
}
2015-09-28 08:23:31 +13:00
pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
self.print_name(lifetime.name)
}
2015-09-28 08:23:31 +13:00
pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> {
self.print_lifetime(&lifetime.lifetime)?;
2015-07-31 00:04:06 -07:00
let mut sep = ":";
for v in &lifetime.bounds {
word(&mut self.s, sep)?;
self.print_lifetime(v)?;
2015-07-31 00:04:06 -07:00
sep = "+";
}
Ok(())
}
2015-09-28 08:23:31 +13:00
pub fn print_generics(&mut self, generics: &hir::Generics) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
let total = generics.lifetimes.len() + generics.ty_params.len();
if total == 0 {
return Ok(());
}
word(&mut self.s, "<")?;
2015-07-31 00:04:06 -07:00
let mut ints = Vec::new();
for i in 0..total {
ints.push(i);
}
self.commasep(Inconsistent, &ints[..], |s, &idx| {
2015-11-05 21:17:59 +00:00
if idx < generics.lifetimes.len() {
let lifetime = &generics.lifetimes[idx];
s.print_lifetime_def(lifetime)
} else {
let idx = idx - generics.lifetimes.len();
let param = &generics.ty_params[idx];
s.print_ty_param(param)
}
})?;
2015-07-31 00:04:06 -07:00
word(&mut self.s, ">")?;
2015-07-31 00:04:06 -07:00
Ok(())
}
pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> {
self.print_name(param.name)?;
self.print_bounds(":", &param.bounds)?;
2015-07-31 00:04:06 -07:00
match param.default {
Some(ref default) => {
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&default)
2015-07-31 00:04:06 -07:00
}
2015-09-28 08:23:31 +13:00
_ => Ok(()),
2015-07-31 00:04:06 -07:00
}
}
2015-09-28 08:23:31 +13:00
pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
if where_clause.predicates.is_empty() {
2015-11-05 21:17:59 +00:00
return Ok(());
2015-07-31 00:04:06 -07:00
}
space(&mut self.s)?;
self.word_space("where")?;
2015-07-31 00:04:06 -07:00
for (i, predicate) in where_clause.predicates.iter().enumerate() {
if i != 0 {
self.word_space(",")?;
2015-07-31 00:04:06 -07:00
}
match predicate {
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bound_lifetimes,
ref bounded_ty,
ref bounds,
..}) => {
self.print_formal_lifetime_list(bound_lifetimes)?;
self.print_type(&bounded_ty)?;
self.print_bounds(":", bounds)?;
2015-07-31 00:04:06 -07:00
}
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
ref bounds,
..}) => {
self.print_lifetime(lifetime)?;
word(&mut self.s, ":")?;
2015-07-31 00:04:06 -07:00
for (i, bound) in bounds.iter().enumerate() {
self.print_lifetime(bound)?;
2015-07-31 00:04:06 -07:00
if i != 0 {
word(&mut self.s, ":")?;
2015-07-31 00:04:06 -07:00
}
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => {
self.print_path(path, false, 0)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&ty)?;
2015-07-31 00:04:06 -07:00
}
}
}
Ok(())
}
pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
match vp.node {
hir::ViewPathSimple(name, ref path) => {
self.print_path(path, false, 0)?;
2015-07-31 00:04:06 -07:00
2016-03-06 15:54:44 +03:00
if path.segments.last().unwrap().name != name {
space(&mut self.s)?;
self.word_space("as")?;
self.print_name(name)?;
2015-07-31 00:04:06 -07:00
}
Ok(())
}
hir::ViewPathGlob(ref path) => {
self.print_path(path, false, 0)?;
2015-07-31 00:04:06 -07:00
word(&mut self.s, "::*")
}
hir::ViewPathList(ref path, ref segments) => {
2015-07-31 00:04:06 -07:00
if path.segments.is_empty() {
word(&mut self.s, "{")?;
2015-07-31 00:04:06 -07:00
} else {
self.print_path(path, false, 0)?;
word(&mut self.s, "::{")?;
2015-07-31 00:04:06 -07:00
}
self.commasep(Inconsistent, &segments[..], |s, w| {
2015-11-05 21:17:59 +00:00
match w.node {
hir::PathListIdent { name, .. } => {
s.print_name(name)
}
hir::PathListMod { .. } => {
word(&mut s.s, "self")
}
}
})?;
2015-07-31 00:04:06 -07:00
word(&mut self.s, "}")
}
}
}
2015-09-28 08:23:31 +13:00
pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
match mutbl {
hir::MutMutable => self.word_nbsp("mut"),
hir::MutImmutable => Ok(()),
}
}
pub fn print_mt(&mut self, mt: &hir::MutTy) -> io::Result<()> {
self.print_mutability(mt.mutbl)?;
self.print_type(&mt.ty)
2015-07-31 00:04:06 -07:00
}
pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()> {
self.ibox(indent_unit)?;
2015-07-31 00:04:06 -07:00
match input.ty.node {
hir::TyInfer if is_closure => self.print_pat(&input.pat)?,
2015-07-31 00:04:06 -07:00
_ => {
2016-05-08 21:19:29 +03:00
if let Some(eself) = input.to_self() {
self.print_explicit_self(&eself)?;
} else {
2016-03-06 15:54:44 +03:00
let invalid = if let PatKind::Ident(_, name, _) = input.pat.node {
name.node == keywords::Invalid.name()
2016-05-08 21:19:29 +03:00
} else {
false
};
if !invalid {
self.print_pat(&input.pat)?;
word(&mut self.s, ":")?;
space(&mut self.s)?;
2015-07-31 00:04:06 -07:00
}
2016-05-08 21:19:29 +03:00
self.print_type(&input.ty)?;
2015-07-31 00:04:06 -07:00
}
}
}
self.end()
}
pub fn print_fn_output(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
if let hir::DefaultReturn(..) = decl.output {
return Ok(());
}
self.space_if_not_bol()?;
self.ibox(indent_unit)?;
self.word_space("->")?;
2015-07-31 00:04:06 -07:00
match decl.output {
hir::NoReturn(_) => self.word_nbsp("!")?,
2015-07-31 00:04:06 -07:00
hir::DefaultReturn(..) => unreachable!(),
hir::Return(ref ty) => self.print_type(&ty)?,
2015-07-31 00:04:06 -07:00
}
self.end()?;
2015-07-31 00:04:06 -07:00
match decl.output {
hir::Return(ref output) => self.maybe_print_comment(output.span.lo),
2015-09-28 08:23:31 +13:00
_ => Ok(()),
2015-07-31 00:04:06 -07:00
}
}
pub fn print_ty_fn(&mut self,
abi: Abi,
2015-07-31 00:04:06 -07:00
unsafety: hir::Unsafety,
decl: &hir::FnDecl,
name: Option<ast::Name>,
2016-05-08 21:19:29 +03:00
generics: &hir::Generics)
2015-07-31 00:04:06 -07:00
-> io::Result<()> {
self.ibox(indent_unit)?;
2015-07-31 00:04:06 -07:00
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
word(&mut self.s, "for")?;
self.print_generics(generics)?;
2015-07-31 00:04:06 -07:00
}
let generics = hir::Generics {
lifetimes: hir::HirVec::new(),
2015-12-19 04:20:11 +03:00
ty_params: hir::HirVec::new(),
2015-07-31 00:04:06 -07:00
where_clause: hir::WhereClause {
id: ast::DUMMY_NODE_ID,
predicates: hir::HirVec::new(),
2015-07-31 00:04:06 -07:00
},
};
self.print_fn(decl,
2016-03-22 17:58:45 -05:00
unsafety,
hir::Constness::NotConst,
abi,
name,
&generics,
&hir::Inherited)?;
2015-07-31 00:04:06 -07:00
self.end()
}
2015-09-28 08:23:31 +13:00
pub fn maybe_print_trailing_comment(&mut self,
span: codemap::Span,
2015-07-31 00:04:06 -07:00
next_pos: Option<BytePos>)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
2015-07-31 00:04:06 -07:00
let cm = match self.cm {
Some(cm) => cm,
2015-09-28 08:23:31 +13:00
_ => return Ok(()),
2015-07-31 00:04:06 -07:00
};
match self.next_comment() {
Some(ref cmnt) => {
2015-09-28 08:23:31 +13:00
if (*cmnt).style != comments::Trailing {
2015-11-05 21:17:59 +00:00
return Ok(());
2015-09-28 08:23:31 +13:00
}
2015-07-31 00:04:06 -07:00
let span_line = cm.lookup_char_pos(span.hi);
let comment_line = cm.lookup_char_pos((*cmnt).pos);
let mut next = (*cmnt).pos + BytePos(1);
2015-09-28 08:23:31 +13:00
match next_pos {
None => (),
Some(p) => next = p,
}
2015-07-31 00:04:06 -07:00
if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
2015-09-28 08:23:31 +13:00
span_line.line == comment_line.line {
self.print_comment(cmnt)?;
2015-09-28 08:23:31 +13:00
self.cur_cmnt_and_lit.cur_cmnt += 1;
}
2015-07-31 00:04:06 -07:00
}
2015-09-28 08:23:31 +13:00
_ => (),
2015-07-31 00:04:06 -07:00
}
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() {
hardbreak(&mut self.s)?;
2015-07-31 00:04:06 -07:00
}
loop {
match self.next_comment() {
Some(ref cmnt) => {
self.print_comment(cmnt)?;
2015-07-31 00:04:06 -07:00
self.cur_cmnt_and_lit.cur_cmnt += 1;
}
2015-09-28 08:23:31 +13:00
_ => break,
2015-07-31 00:04:06 -07:00
}
}
Ok(())
}
pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
opt_abi: Option<Abi>)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
2015-07-31 00:04:06 -07:00
match opt_abi {
Some(Abi::Rust) => Ok(()),
2015-07-31 00:04:06 -07:00
Some(abi) => {
self.word_nbsp("extern")?;
2015-07-31 00:04:06 -07:00
self.word_nbsp(&abi.to_string())
}
2015-09-28 08:23:31 +13:00
None => Ok(()),
2015-07-31 00:04:06 -07:00
}
}
pub fn print_extern_opt_abi(&mut self, opt_abi: Option<Abi>) -> io::Result<()> {
2015-07-31 00:04:06 -07:00
match opt_abi {
Some(abi) => {
self.word_nbsp("extern")?;
2015-07-31 00:04:06 -07:00
self.word_nbsp(&abi.to_string())
}
2015-09-28 08:23:31 +13:00
None => Ok(()),
2015-07-31 00:04:06 -07:00
}
}
pub fn print_fn_header_info(&mut self,
unsafety: hir::Unsafety,
constness: hir::Constness,
abi: Abi,
vis: &hir::Visibility)
2015-09-28 08:23:31 +13:00
-> io::Result<()> {
word(&mut self.s, &visibility_qualified(vis, ""))?;
self.print_unsafety(unsafety)?;
2015-07-31 00:04:06 -07:00
match constness {
hir::Constness::NotConst => {}
hir::Constness::Const => self.word_nbsp("const")?,
2015-07-31 00:04:06 -07:00
}
if abi != Abi::Rust {
self.word_nbsp("extern")?;
self.word_nbsp(&abi.to_string())?;
2015-07-31 00:04:06 -07:00
}
word(&mut self.s, "fn")
}
pub fn print_unsafety(&mut self, s: hir::Unsafety) -> io::Result<()> {
match s {
hir::Unsafety::Normal => Ok(()),
hir::Unsafety::Unsafe => self.word_nbsp("unsafe"),
}
}
}
// Dup'ed from parse::classify, but adapted for the HIR.
/// Does this expression require a semicolon to be treated
/// as a statement? The negation of this: 'can this expression
/// be used as a statement without a semicolon' -- is used
/// as an early-bail-out in the parser so that, for instance,
/// if true {...} else {...}
/// |x| 5
/// isn't parsed as (if true {...} else {...} | x) | 5
fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool {
match e.node {
2015-09-28 08:23:31 +13:00
hir::ExprIf(..) |
hir::ExprMatch(..) |
hir::ExprBlock(_) |
hir::ExprWhile(..) |
hir::ExprLoop(..) => false,
_ => true,
2015-07-31 00:04:06 -07:00
}
}
/// this statement requires a semicolon after it.
/// note that in one case (stmt_semi), we've already
/// seen the semicolon, and thus don't need another.
fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool {
match *stmt {
hir::StmtDecl(ref d, _) => {
match d.node {
hir::DeclLocal(_) => true,
2015-09-28 08:23:31 +13:00
hir::DeclItem(_) => false,
2015-07-31 00:04:06 -07:00
}
}
2015-09-28 08:23:31 +13:00
hir::StmtExpr(ref e, _) => {
expr_requires_semi_to_be_stmt(&e)
2015-09-28 08:23:31 +13:00
}
hir::StmtSemi(..) => {
false
}
2015-07-31 00:04:06 -07:00
}
}