rustc: leave only one free top-level function in ppaux, and private.

This commit is contained in:
Eduard Burtescu 2015-06-16 01:10:55 +03:00
parent 96ad4a4863
commit 6061707348
6 changed files with 331 additions and 367 deletions
src
librustc
librustc_borrowck/borrowck
librustc_trans/trans
librustc_typeck

@ -75,6 +75,7 @@ use std::collections::HashSet;
use ast_map;
use middle::def;
use middle::infer;
use middle::region;
use middle::subst;
use middle::ty::{self, Ty};
use middle::ty::{Region, ReFree};
@ -84,16 +85,135 @@ use std::string::String;
use syntax::ast;
use syntax::ast_util::name_to_dummy_lifetime;
use syntax::owned_slice::OwnedSlice;
use syntax::codemap;
use syntax::codemap::{Pos, Span};
use syntax::parse::token;
use syntax::print::pprust;
use syntax::ptr::P;
use util::ppaux::note_and_explain_region;
// Note: only import UserString, not Repr, since user-facing error
// messages shouldn't include debug serializations.
use util::ppaux::UserString;
pub fn note_and_explain_region(tcx: &ty::ctxt,
prefix: &str,
region: ty::Region,
suffix: &str) {
fn item_scope_tag(item: &ast::Item) -> &'static str {
match item.node {
ast::ItemImpl(..) => "impl",
ast::ItemStruct(..) => "struct",
ast::ItemEnum(..) => "enum",
ast::ItemTrait(..) => "trait",
ast::ItemFn(..) => "function body",
_ => "item"
}
}
fn explain_span(tcx: &ty::ctxt, heading: &str, span: Span)
-> (String, Option<Span>) {
let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
(format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
Some(span))
}
let (description, span) = match region {
ty::ReScope(scope) => {
let new_string;
let unknown_scope = || {
format!("{}unknown scope: {:?}{}. Please report a bug.",
prefix, scope, suffix)
};
let span = match scope.span(&tcx.map) {
Some(s) => s,
None => return tcx.sess.note(&unknown_scope())
};
let tag = match tcx.map.find(scope.node_id()) {
Some(ast_map::NodeBlock(_)) => "block",
Some(ast_map::NodeExpr(expr)) => match expr.node {
ast::ExprCall(..) => "call",
ast::ExprMethodCall(..) => "method call",
ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => "while let",
ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) => "for",
ast::ExprMatch(..) => "match",
_ => "expression",
},
Some(ast_map::NodeStmt(_)) => "statement",
Some(ast_map::NodeItem(it)) => item_scope_tag(&*it),
Some(_) | None => {
return tcx.sess.span_note(span, &unknown_scope());
}
};
let scope_decorated_tag = match scope {
region::CodeExtent::Misc(_) => tag,
region::CodeExtent::ParameterScope { .. } => {
"scope of parameters for function"
}
region::CodeExtent::DestructionScope(_) => {
new_string = format!("destruction scope surrounding {}", tag);
&new_string[..]
}
region::CodeExtent::Remainder(r) => {
new_string = format!("block suffix following statement {}",
r.first_statement_index);
&new_string[..]
}
};
explain_span(tcx, scope_decorated_tag, span)
}
ty::ReFree(ref fr) => {
let prefix = match fr.bound_region {
ty::BrAnon(idx) => {
format!("the anonymous lifetime #{} defined on", idx + 1)
}
ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
_ => {
format!("the lifetime {} as defined on",
fr.bound_region.user_string(tcx))
}
};
match tcx.map.find(fr.scope.node_id) {
Some(ast_map::NodeBlock(ref blk)) => {
let (msg, opt_span) = explain_span(tcx, "block", blk.span);
(format!("{} {}", prefix, msg), opt_span)
}
Some(ast_map::NodeItem(it)) => {
let tag = item_scope_tag(&*it);
let (msg, opt_span) = explain_span(tcx, tag, it.span);
(format!("{} {}", prefix, msg), opt_span)
}
Some(_) | None => {
// this really should not happen
(format!("{} unknown free region bounded by scope {:?}",
prefix, fr.scope), None)
}
}
}
ty::ReStatic => ("the static lifetime".to_owned(), None),
ty::ReEmpty => ("the empty lifetime".to_owned(), None),
ty::ReEarlyBound(ref data) => {
(format!("{}", token::get_name(data.name)), None)
}
// I believe these cases should not occur (except when debugging,
// perhaps)
ty::ReInfer(_) | ty::ReLateBound(..) => {
(format!("lifetime {:?}", region), None)
}
};
let message = format!("{}{}{}", prefix, description, suffix);
if let Some(span) = span {
tcx.sess.span_note(span, &message);
} else {
tcx.sess.note(&message);
}
}
pub trait ErrorReporting<'tcx> {
fn report_region_errors(&self,
errors: &Vec<RegionResolutionError<'tcx>>);
@ -161,7 +281,7 @@ trait ErrorReportingHelpers<'tcx> {
ident: ast::Ident,
opt_explicit_self: Option<&ast::ExplicitSelf_>,
generics: &ast::Generics,
span: codemap::Span);
span: Span);
}
impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
@ -1430,7 +1550,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
ident: ast::Ident,
opt_explicit_self: Option<&ast::ExplicitSelf_>,
generics: &ast::Generics,
span: codemap::Span) {
span: Span) {
let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, ident,
opt_explicit_self, generics);
let msg = format!("consider using an explicit lifetime \

@ -48,6 +48,7 @@ use middle::def::{self, DefMap, ExportMap};
use middle::dependency_format;
use middle::fast_reject;
use middle::free_region::FreeRegionMap;
use middle::infer::error_reporting::note_and_explain_region;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::mem_categorization as mc;
use middle::region;
@ -61,7 +62,6 @@ use middle::traits;
use middle::ty;
use middle::ty_fold::{self, TypeFoldable, TypeFolder};
use middle::ty_walk::{self, TypeWalker};
use util::ppaux::note_and_explain_region;
use util::ppaux::{Repr, UserString};
use util::common::{memoized, ErrorReported};
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};

@ -32,7 +32,7 @@ use std::collections::hash_state::HashState;
use std::hash::Hash;
use std::rc::Rc;
use syntax::abi;
use syntax::codemap::{Span, Pos};
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::print::pprust;
use syntax::ptr::P;
@ -49,342 +49,7 @@ pub trait UserString<'tcx> : Repr<'tcx> {
fn user_string(&self, tcx: &ctxt<'tcx>) -> String;
}
pub fn note_and_explain_region(cx: &ctxt,
prefix: &str,
region: ty::Region,
suffix: &str) {
let (description, span) = explain_region_and_span(cx, region);
let message = format!("{}{}{}", prefix, description, suffix);
if let Some(span) = span {
cx.sess.span_note(span, &message);
} else {
cx.sess.note(&message);
}
}
/// When a free region is associated with `item`, how should we describe the item in the error
/// message.
fn item_scope_tag(item: &ast::Item) -> &'static str {
match item.node {
ast::ItemImpl(..) => "impl",
ast::ItemStruct(..) => "struct",
ast::ItemEnum(..) => "enum",
ast::ItemTrait(..) => "trait",
ast::ItemFn(..) => "function body",
_ => "item"
}
}
fn explain_region_and_span(cx: &ctxt, region: ty::Region)
-> (String, Option<Span>) {
return match region {
ReScope(scope) => {
let new_string;
let on_unknown_scope = || {
(format!("unknown scope: {:?}. Please report a bug.", scope), None)
};
let span = match scope.span(&cx.map) {
Some(s) => s,
None => return on_unknown_scope(),
};
let tag = match cx.map.find(scope.node_id()) {
Some(ast_map::NodeBlock(_)) => "block",
Some(ast_map::NodeExpr(expr)) => match expr.node {
ast::ExprCall(..) => "call",
ast::ExprMethodCall(..) => "method call",
ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => "while let",
ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) => "for",
ast::ExprMatch(..) => "match",
_ => "expression",
},
Some(ast_map::NodeStmt(_)) => "statement",
Some(ast_map::NodeItem(it)) => item_scope_tag(&*it),
Some(_) | None => {
// this really should not happen
return on_unknown_scope();
}
};
let scope_decorated_tag = match scope {
region::CodeExtent::Misc(_) => tag,
region::CodeExtent::ParameterScope { .. } => {
"scope of parameters for function"
}
region::CodeExtent::DestructionScope(_) => {
new_string = format!("destruction scope surrounding {}", tag);
&*new_string
}
region::CodeExtent::Remainder(r) => {
new_string = format!("block suffix following statement {}",
r.first_statement_index);
&*new_string
}
};
explain_span(cx, scope_decorated_tag, span)
}
ReFree(ref fr) => {
let prefix = match fr.bound_region {
BrAnon(idx) => {
format!("the anonymous lifetime #{} defined on", idx + 1)
}
BrFresh(_) => "an anonymous lifetime defined on".to_string(),
_ => {
format!("the lifetime {} as defined on",
fr.bound_region.user_string(cx))
}
};
match cx.map.find(fr.scope.node_id) {
Some(ast_map::NodeBlock(ref blk)) => {
let (msg, opt_span) = explain_span(cx, "block", blk.span);
(format!("{} {}", prefix, msg), opt_span)
}
Some(ast_map::NodeItem(it)) => {
let tag = item_scope_tag(&*it);
let (msg, opt_span) = explain_span(cx, tag, it.span);
(format!("{} {}", prefix, msg), opt_span)
}
Some(_) | None => {
// this really should not happen
(format!("{} unknown free region bounded by scope {:?}", prefix, fr.scope), None)
}
}
}
ReStatic => { ("the static lifetime".to_string(), None) }
ReEmpty => { ("the empty lifetime".to_string(), None) }
ReEarlyBound(ref data) => {
(format!("{}", token::get_name(data.name)), None)
}
// I believe these cases should not occur (except when debugging,
// perhaps)
ty::ReInfer(_) | ty::ReLateBound(..) => {
(format!("lifetime {:?}", region), None)
}
};
fn explain_span(cx: &ctxt, heading: &str, span: Span)
-> (String, Option<Span>) {
let lo = cx.sess.codemap().lookup_char_pos_adj(span.lo);
(format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
Some(span))
}
}
pub fn mutability_to_string(m: ast::Mutability) -> String {
match m {
ast::MutMutable => "mut ".to_string(),
ast::MutImmutable => "".to_string(),
}
}
pub fn mt_to_string<'tcx>(cx: &ctxt<'tcx>, m: &mt<'tcx>) -> String {
format!("{}{}",
mutability_to_string(m.mutbl),
m.ty.user_string(cx))
}
pub fn vec_map_to_string<T, F>(ts: &[T], f: F) -> String where
F: FnMut(&T) -> String,
{
let tstrs = ts.iter().map(f).collect::<Vec<String>>();
format!("[{}]", tstrs.connect(", "))
}
fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
opt_def_id: Option<ast::DefId>,
unsafety: ast::Unsafety,
abi: abi::Abi,
ident: Option<ast::Ident>,
sig: &ty::PolyFnSig<'tcx>)
-> String {
let mut s = String::new();
match unsafety {
ast::Unsafety::Normal => {}
ast::Unsafety::Unsafe => {
s.push_str(&unsafety.to_string());
s.push(' ');
}
};
if abi != abi::Rust {
s.push_str(&format!("extern {} ", abi.to_string()));
};
s.push_str("fn");
match ident {
Some(i) => {
s.push(' ');
s.push_str(&token::get_ident(i));
}
_ => { }
}
push_sig_to_string(cx, &mut s, '(', ')', sig);
match opt_def_id {
Some(def_id) => {
s.push_str(" {");
let path_str = ty::item_path_str(cx, def_id);
s.push_str(&path_str[..]);
s.push_str("}");
}
None => { }
}
s
}
fn closure_to_string<'tcx>(cx: &ctxt<'tcx>,
cty: &ty::ClosureTy<'tcx>,
did: &ast::DefId)
-> String {
let mut s = String::new();
s.push_str("[closure");
push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
if cx.sess.verbose() {
s.push_str(&format!(" id={:?}]", did));
} else {
s.push(']');
}
s
}
fn push_sig_to_string<'tcx>(cx: &ctxt<'tcx>,
s: &mut String,
bra: char,
ket: char,
sig: &ty::PolyFnSig<'tcx>) {
s.push(bra);
let strs = sig.0.inputs
.iter()
.map(|a| a.user_string(cx))
.collect::<Vec<_>>();
s.push_str(&strs.connect(", "));
if sig.0.variadic {
s.push_str(", ...");
}
s.push(ket);
match sig.0.output {
ty::FnConverging(t) => {
if !ty::type_is_nil(t) {
s.push_str(" -> ");
s.push_str(& t.user_string(cx));
}
}
ty::FnDiverging => {
s.push_str(" -> !");
}
}
}
fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
let print_var_ids = cx.sess.verbose();
match ty {
ty::TyVar(ref vid) if print_var_ids => vid.repr(cx),
ty::IntVar(ref vid) if print_var_ids => vid.repr(cx),
ty::FloatVar(ref vid) if print_var_ids => vid.repr(cx),
ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => format!("_"),
ty::FreshTy(v) => format!("FreshTy({})", v),
ty::FreshIntTy(v) => format!("FreshIntTy({})", v),
ty::FreshFloatTy(v) => format!("FreshFloatTy({})", v)
}
}
// pretty print the structural type representation:
match typ.sty {
TyBool => "bool".to_string(),
TyChar => "char".to_string(),
TyInt(t) => ast_util::int_ty_to_string(t, None).to_string(),
TyUint(t) => ast_util::uint_ty_to_string(t, None).to_string(),
TyFloat(t) => ast_util::float_ty_to_string(t).to_string(),
TyBox(typ) => format!("Box<{}>", typ.user_string(cx)),
TyRawPtr(ref tm) => {
format!("*{} {}", match tm.mutbl {
ast::MutMutable => "mut",
ast::MutImmutable => "const",
}, tm.ty.user_string(cx))
}
TyRef(r, ref tm) => {
let mut buf = "&".to_owned();
buf.push_str(&r.user_string(cx));
if !buf.is_empty() {
buf.push_str(" ");
}
buf.push_str(&mt_to_string(cx, tm));
buf
}
TyTuple(ref elems) => {
let strs = elems
.iter()
.map(|elem| elem.user_string(cx))
.collect::<Vec<_>>();
match &strs[..] {
[ref string] => format!("({},)", string),
strs => format!("({})", strs.connect(", "))
}
}
TyBareFn(opt_def_id, ref f) => {
bare_fn_to_string(cx, opt_def_id, f.unsafety, f.abi, None, &f.sig)
}
TyInfer(infer_ty) => infer_ty_to_string(cx, infer_ty),
TyError => "[type error]".to_string(),
TyParam(ref param_ty) => param_ty.user_string(cx),
TyEnum(did, substs) | TyStruct(did, substs) => {
let base = ty::item_path_str(cx, did);
parameterized(cx, &base, substs, did, &[],
|| ty::lookup_item_type(cx, did).generics)
}
TyTrait(ref data) => {
data.user_string(cx)
}
ty::TyProjection(ref data) => {
format!("<{} as {}>::{}",
data.trait_ref.self_ty().user_string(cx),
data.trait_ref.user_string(cx),
data.item_name.user_string(cx))
}
TyStr => "str".to_string(),
TyClosure(ref did, substs) => {
let closure_tys = cx.closure_tys.borrow();
closure_tys.get(did).map(|closure_type| {
closure_to_string(cx, &closure_type.subst(cx, substs), did)
}).unwrap_or_else(|| {
let id_str = if cx.sess.verbose() {
format!(" id={:?}", did)
} else {
"".to_owned()
};
if did.krate == ast::LOCAL_CRATE {
let span = cx.map.span(did.node);
format!("[closure {}{}]", span.repr(cx), id_str)
} else {
format!("[closure{}]", id_str)
}
})
}
TyArray(t, sz) => {
format!("[{}; {}]", t.user_string(cx), sz)
}
TySlice(t) => {
format!("[{}]", t.user_string(cx))
}
}
}
fn parameterized<'tcx, GG>(cx: &ctxt<'tcx>,
base: &str,
substs: &subst::Substs<'tcx>,
did: ast::DefId,
projections: &[ty::ProjectionPredicate<'tcx>],
@ -392,6 +57,7 @@ fn parameterized<'tcx, GG>(cx: &ctxt<'tcx>,
-> String
where GG : FnOnce() -> ty::Generics<'tcx>
{
let base = ty::item_path_str(cx, did);
if cx.sess.verbose() {
let mut strings = vec![];
match substs.regions {
@ -557,19 +223,15 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Box<T> {
}
}
fn repr_vec<'tcx, T:Repr<'tcx>>(tcx: &ctxt<'tcx>, v: &[T]) -> String {
vec_map_to_string(v, |t| t.repr(tcx))
}
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for [T] {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
repr_vec(tcx, self)
format!("[{}]", self.iter().map(|t| t.repr(tcx)).collect::<Vec<_>>().connect(", "))
}
}
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice<T> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
repr_vec(tcx, &self[..])
self[..].repr(tcx)
}
}
@ -577,7 +239,7 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice<T> {
// autoderef cannot convert the &[T] handler
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec<T> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
repr_vec(tcx, &self[..])
self[..].repr(tcx)
}
}
@ -618,9 +280,7 @@ type TraitAndProjections<'tcx> =
impl<'tcx> UserString<'tcx> for TraitAndProjections<'tcx> {
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
let &(ref trait_ref, ref projection_bounds) = self;
let base = ty::item_path_str(tcx, trait_ref.def_id);
parameterized(tcx,
&base,
trait_ref.substs,
trait_ref.def_id,
&projection_bounds[..],
@ -684,7 +344,9 @@ impl<'tcx> Repr<'tcx> for ty::TyS<'tcx> {
impl<'tcx> Repr<'tcx> for ty::mt<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
mt_to_string(tcx, self)
format!("{}{}",
if self.mutbl == ast::MutMutable { "mut " } else { "" },
self.ty.user_string(tcx))
}
}
@ -751,9 +413,7 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
// when printing out the debug representation, we don't need
// to enumerate the `for<...>` etc because the debruijn index
// tells you everything you need to know.
let base = ty::item_path_str(tcx, self.def_id);
let result = parameterized(tcx, &base, self.substs, self.def_id, &[],
|| ty::lookup_trait_def(tcx, self.def_id).generics.clone());
let result = self.user_string(tcx);
match self.substs.self_ty() {
None => result,
Some(sty) => format!("<{} as {}>", sty.repr(tcx), result)
@ -1290,15 +950,196 @@ impl<'tcx, T> UserString<'tcx> for ty::Binder<T>
impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
let path_str = ty::item_path_str(tcx, self.def_id);
parameterized(tcx, &path_str, self.substs, self.def_id, &[],
parameterized(tcx, self.substs, self.def_id, &[],
|| ty::lookup_trait_def(tcx, self.def_id).generics.clone())
}
}
impl<'tcx> UserString<'tcx> for ty::TyS<'tcx> {
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
ty_to_string(tcx, self)
fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
opt_def_id: Option<ast::DefId>,
unsafety: ast::Unsafety,
abi: abi::Abi,
ident: Option<ast::Ident>,
sig: &ty::PolyFnSig<'tcx>)
-> String {
let mut s = String::new();
match unsafety {
ast::Unsafety::Normal => {}
ast::Unsafety::Unsafe => {
s.push_str(&unsafety.to_string());
s.push(' ');
}
};
if abi != abi::Rust {
s.push_str(&format!("extern {} ", abi.to_string()));
};
s.push_str("fn");
match ident {
Some(i) => {
s.push(' ');
s.push_str(&token::get_ident(i));
}
_ => { }
}
push_sig_to_string(cx, &mut s, '(', ')', sig);
match opt_def_id {
Some(def_id) => {
s.push_str(" {");
let path_str = ty::item_path_str(cx, def_id);
s.push_str(&path_str[..]);
s.push_str("}");
}
None => { }
}
s
}
fn closure_to_string<'tcx>(cx: &ctxt<'tcx>,
cty: &ty::ClosureTy<'tcx>,
did: &ast::DefId)
-> String {
let mut s = String::new();
s.push_str("[closure");
push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
if cx.sess.verbose() {
s.push_str(&format!(" id={:?}]", did));
} else {
s.push(']');
}
s
}
fn push_sig_to_string<'tcx>(cx: &ctxt<'tcx>,
s: &mut String,
bra: char,
ket: char,
sig: &ty::PolyFnSig<'tcx>) {
s.push(bra);
let strs = sig.0.inputs
.iter()
.map(|a| a.user_string(cx))
.collect::<Vec<_>>();
s.push_str(&strs.connect(", "));
if sig.0.variadic {
s.push_str(", ...");
}
s.push(ket);
match sig.0.output {
ty::FnConverging(t) => {
if !ty::type_is_nil(t) {
s.push_str(" -> ");
s.push_str(& t.user_string(cx));
}
}
ty::FnDiverging => {
s.push_str(" -> !");
}
}
}
fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
let print_var_ids = cx.sess.verbose();
match ty {
ty::TyVar(ref vid) if print_var_ids => vid.repr(cx),
ty::IntVar(ref vid) if print_var_ids => vid.repr(cx),
ty::FloatVar(ref vid) if print_var_ids => vid.repr(cx),
ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => format!("_"),
ty::FreshTy(v) => format!("FreshTy({})", v),
ty::FreshIntTy(v) => format!("FreshIntTy({})", v),
ty::FreshFloatTy(v) => format!("FreshFloatTy({})", v)
}
}
// pretty print the structural type representation:
match self.sty {
TyBool => "bool".to_string(),
TyChar => "char".to_string(),
TyInt(t) => ast_util::int_ty_to_string(t, None).to_string(),
TyUint(t) => ast_util::uint_ty_to_string(t, None).to_string(),
TyFloat(t) => ast_util::float_ty_to_string(t).to_string(),
TyBox(typ) => format!("Box<{}>", typ.user_string(tcx)),
TyRawPtr(ref tm) => {
format!("*{} {}", match tm.mutbl {
ast::MutMutable => "mut",
ast::MutImmutable => "const",
}, tm.ty.user_string(tcx))
}
TyRef(r, ref tm) => {
let mut buf = "&".to_owned();
buf.push_str(&r.user_string(tcx));
if !buf.is_empty() {
buf.push_str(" ");
}
buf.push_str(&tm.repr(tcx));
buf
}
TyTuple(ref elems) => {
let strs = elems
.iter()
.map(|elem| elem.user_string(tcx))
.collect::<Vec<_>>();
match &strs[..] {
[ref string] => format!("({},)", string),
strs => format!("({})", strs.connect(", "))
}
}
TyBareFn(opt_def_id, ref f) => {
bare_fn_to_string(tcx, opt_def_id, f.unsafety, f.abi, None, &f.sig)
}
TyInfer(infer_ty) => infer_ty_to_string(tcx, infer_ty),
TyError => "[type error]".to_string(),
TyParam(ref param_ty) => param_ty.user_string(tcx),
TyEnum(did, substs) | TyStruct(did, substs) => {
parameterized(tcx, substs, did, &[],
|| ty::lookup_item_type(tcx, did).generics)
}
TyTrait(ref data) => {
data.user_string(tcx)
}
ty::TyProjection(ref data) => {
format!("<{} as {}>::{}",
data.trait_ref.self_ty().user_string(tcx),
data.trait_ref.user_string(tcx),
data.item_name.user_string(tcx))
}
TyStr => "str".to_string(),
TyClosure(ref did, substs) => {
let closure_tys = tcx.closure_tys.borrow();
closure_tys.get(did).map(|closure_type| {
closure_to_string(tcx, &closure_type.subst(tcx, substs), did)
}).unwrap_or_else(|| {
let id_str = if tcx.sess.verbose() {
format!(" id={:?}", did)
} else {
"".to_owned()
};
if did.krate == ast::LOCAL_CRATE {
let span = tcx.map.span(did.node);
format!("[closure {}{}]", span.repr(tcx), id_str)
} else {
format!("[closure{}]", id_str)
}
})
}
TyArray(t, sz) => {
format!("[{}; {}]", t.user_string(tcx), sz)
}
TySlice(t) => {
format!("[{}]", t.user_string(tcx))
}
}
}
}

@ -28,11 +28,12 @@ use rustc::middle::dataflow::BitwiseOperator;
use rustc::middle::dataflow::DataFlowOperator;
use rustc::middle::dataflow::KillFrom;
use rustc::middle::expr_use_visitor as euv;
use rustc::middle::mem_categorization as mc;
use rustc::middle::free_region::FreeRegionMap;
use rustc::middle::infer::error_reporting::note_and_explain_region;
use rustc::middle::mem_categorization as mc;
use rustc::middle::region;
use rustc::middle::ty::{self, Ty};
use rustc::util::ppaux::{note_and_explain_region, Repr, UserString};
use rustc::util::ppaux::{Repr, UserString};
use std::mem;
use std::rc::Rc;
use std::string::String;

@ -217,7 +217,7 @@ use middle::ty::{self, Ty};
use session::config::{NoDebugInfo, FullDebugInfo};
use util::common::indenter;
use util::nodemap::FnvHashMap;
use util::ppaux::{Repr, vec_map_to_string};
use util::ppaux::Repr;
use std;
use std::cmp::Ordering;
@ -937,11 +937,11 @@ fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
chk: &FailureHandler,
has_genuine_default: bool)
-> Block<'blk, 'tcx> {
debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals={})",
debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals=[{}])",
bcx.to_str(),
bcx.expr_to_string(guard_expr),
m.repr(bcx.tcx()),
vec_map_to_string(vals, |v| bcx.val_to_string(*v)));
vals.iter().map(|v| bcx.val_to_string(*v)).collect::<Vec<_>>().connect(", "));
let _indenter = indenter();
let mut bcx = insert_lllocals(bcx, &data.bindings_map, None);
@ -983,10 +983,10 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
vals: &[ValueRef],
chk: &FailureHandler,
has_genuine_default: bool) {
debug!("compile_submatch(bcx={}, m={}, vals={})",
debug!("compile_submatch(bcx={}, m={}, vals=[{}])",
bcx.to_str(),
m.repr(bcx.tcx()),
vec_map_to_string(vals, |v| bcx.val_to_string(*v)));
vals.iter().map(|v| bcx.val_to_string(*v)).collect::<Vec<_>>().connect(", "));
let _indenter = indenter();
let _icx = push_ctxt("match::compile_submatch");
let mut bcx = bcx;

@ -61,7 +61,7 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ExplicitRscope
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
use util::common::{ErrorReported, FN_OUTPUT_NAME};
use util::nodemap::FnvHashSet;
use util::ppaux::{self, Repr, UserString};
use util::ppaux::{Repr, UserString};
use std::iter::repeat;
use std::slice;
@ -985,19 +985,21 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
});
match (&ty.node, full_span) {
(&ast::TyRptr(None, ref mut_ty), Some(full_span)) => {
let mutbl_str = if mut_ty.mutbl == ast::MutMutable { "mut " } else { "" };
this.tcx().sess
.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
format!("&{}({} +{})",
ppaux::mutability_to_string(mut_ty.mutbl),
mutbl_str,
pprust::ty_to_string(&*mut_ty.ty),
pprust::bounds_to_string(bounds)));
}
(&ast::TyRptr(Some(ref lt), ref mut_ty), Some(full_span)) => {
let mutbl_str = if mut_ty.mutbl == ast::MutMutable { "mut " } else { "" };
this.tcx().sess
.span_suggestion(full_span, "try adding parentheses (per RFC 438):",
format!("&{} {}({} +{})",
pprust::lifetime_to_string(lt),
ppaux::mutability_to_string(mut_ty.mutbl),
mutbl_str,
pprust::ty_to_string(&*mut_ty.ty),
pprust::bounds_to_string(bounds)));
}