// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-use metadata::encoder;
-use middle::ty::{ReSkolemized, ReVar};
-use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
-use middle::ty::{br_fresh, ctxt, field};
-use middle::ty::{mt, t, param_ty};
-use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region,
- re_empty};
-use middle::ty::{ty_bool, ty_bot, ty_box, ty_struct, ty_enum};
-use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure};
-use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
-use middle::ty::{ty_ptr, ty_rptr, ty_self, ty_tup, ty_type, ty_uniq};
-use middle::ty::{ty_trait, ty_int};
-use middle::ty::{ty_uint, ty_unboxed_vec, ty_infer};
-use middle::ty;
-use middle::typeck;
-use syntax::abi::AbiSet;
-use syntax::ast_map;
-use syntax::codemap::span;
+use hir::def_id::DefId;
+use ty::subst::{self, Subst, Substs};
+use hir::map::definitions::DefPathData;
+use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
+use ty::{TyBool, TyChar, TyAdt};
+use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
+use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
+use ty::TyClosure;
+use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
+use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::fold::{TypeFolder, TypeVisitor};
+
+use std::cell::Cell;
+use std::fmt;
+use std::usize;
+
+use syntax::abi::Abi;
use syntax::parse::token;
-use syntax::print::pprust;
-use syntax::{ast, ast_util};
-
-/// Produces a string suitable for debugging output.
-pub trait Repr {
- fn repr(&self, tcx: ctxt) -> ~str;
-}
-
-/// Produces a string suitable for showing to the user.
-pub trait UserString {
- fn user_string(&self, tcx: ctxt) -> ~str;
-}
-
-pub fn note_and_explain_region(cx: ctxt,
- prefix: &str,
- region: ty::Region,
- suffix: &str) {
- match explain_region_and_span(cx, region) {
- (ref str, Some(span)) => {
- cx.sess.span_note(
- span,
- fmt!("%s%s%s", prefix, (*str), suffix));
- }
- (ref str, None) => {
- cx.sess.note(
- fmt!("%s%s%s", prefix, (*str), suffix));
- }
- }
-}
-
-/// Returns a string like "the block at 27:31" that attempts to explain a
-/// lifetime in a way it might plausibly be understood.
-pub fn explain_region(cx: ctxt, region: ty::Region) -> ~str {
- let (res, _) = explain_region_and_span(cx, region);
- return res;
-}
-
-
-pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
- -> (~str, Option<span>) {
- return match region {
- re_scope(node_id) => {
- match cx.items.find(&node_id) {
- Some(&ast_map::node_block(ref blk)) => {
- explain_span(cx, "block", blk.span)
- }
- Some(&ast_map::node_callee_scope(expr)) => {
- explain_span(cx, "callee", expr.span)
- }
- Some(&ast_map::node_expr(expr)) => {
- match expr.node {
- ast::expr_call(*) => explain_span(cx, "call", expr.span),
- ast::expr_method_call(*) => {
- explain_span(cx, "method call", expr.span)
- },
- ast::expr_match(*) => explain_span(cx, "match", expr.span),
- _ => explain_span(cx, "expression", expr.span)
- }
- }
- Some(&ast_map::node_stmt(stmt)) => {
- explain_span(cx, "statement", stmt.span)
- }
- Some(&ast_map::node_item(it, _)) if (match it.node {
- ast::item_fn(*) => true, _ => false}) => {
- explain_span(cx, "function body", it.span)
- }
- Some(_) | None => {
- // this really should not happen
- (fmt!("unknown scope: %d. Please report a bug.", node_id),
- None)
- }
- }
- }
-
- re_free(ref fr) => {
- let prefix = match fr.bound_region {
- br_anon(idx) => fmt!("the anonymous lifetime #%u defined on",
- idx + 1),
- br_fresh(_) => fmt!("an anonymous lifetime defined on"),
- _ => fmt!("the lifetime %s as defined on",
- bound_region_ptr_to_str(cx, fr.bound_region))
- };
+use syntax::ast::CRATE_NODE_ID;
+use hir;
- match cx.items.find(&fr.scope_id) {
- Some(&ast_map::node_block(ref blk)) => {
- let (msg, opt_span) = explain_span(cx, "block", blk.span);
- (fmt!("%s %s", prefix, msg), opt_span)
- }
- Some(_) | None => {
- // this really should not happen
- (fmt!("%s node %d", prefix, fr.scope_id), None)
- }
- }
- }
+pub fn verbose() -> bool {
+ ty::tls::with(|tcx| tcx.sess.verbose())
+}
- re_static => { (~"the static lifetime", None) }
+fn fn_sig(f: &mut fmt::Formatter,
+ inputs: &[Ty],
+ variadic: bool,
+ output: Ty)
+ -> fmt::Result {
+ write!(f, "(")?;
+ let mut inputs = inputs.iter();
+ if let Some(&ty) = inputs.next() {
+ write!(f, "{}", ty)?;
+ for &ty in inputs {
+ write!(f, ", {}", ty)?;
+ }
+ if variadic {
+ write!(f, ", ...")?;
+ }
+ }
+ write!(f, ")")?;
+ if !output.is_nil() {
+ write!(f, " -> {}", output)?;
+ }
- re_empty => { (~"the empty lifetime", None) }
+ Ok(())
+}
- // I believe these cases should not occur (except when debugging,
- // perhaps)
- re_infer(_) | re_bound(_) => {
- (fmt!("lifetime %?", region), None)
- }
+pub fn parameterized(f: &mut fmt::Formatter,
+ substs: &subst::Substs,
+ mut did: DefId,
+ projections: &[ty::ProjectionPredicate])
+ -> fmt::Result {
+ let key = ty::tls::with(|tcx| tcx.def_key(did));
+ let mut item_name = if let Some(name) = key.disambiguated_data.data.get_opt_name() {
+ Some(name)
+ } else {
+ did.index = key.parent.unwrap_or_else(
+ || bug!("finding type for {:?}, encountered def-id {:?} with no parent",
+ did, did));
+ parameterized(f, substs, did, projections)?;
+ return write!(f, "::{}", key.disambiguated_data.data.as_interned_str());
};
- fn explain_span(cx: ctxt, heading: &str, span: span)
- -> (~str, Option<span>)
- {
- let lo = cx.sess.codemap.lookup_char_pos_adj(span.lo);
- (fmt!("the %s at %u:%u", heading,
- lo.line, lo.col.to_uint()), Some(span))
+ let mut verbose = false;
+ let mut num_supplied_defaults = 0;
+ let mut has_self = false;
+ let mut num_regions = 0;
+ let mut num_types = 0;
+ let mut is_value_path = false;
+ let fn_trait_kind = ty::tls::with(|tcx| {
+ // Unfortunately, some kinds of items (e.g., closures) don't have
+ // generics. So walk back up the find the closest parent that DOES
+ // have them.
+ let mut item_def_id = did;
+ loop {
+ let key = tcx.def_key(item_def_id);
+ match key.disambiguated_data.data {
+ DefPathData::TypeNs(_) => {
+ break;
+ }
+ DefPathData::ValueNs(_) | DefPathData::EnumVariant(_) => {
+ is_value_path = true;
+ break;
+ }
+ _ => {
+ // if we're making a symbol for something, there ought
+ // to be a value or type-def or something in there
+ // *somewhere*
+ item_def_id.index = key.parent.unwrap_or_else(|| {
+ bug!("finding type for {:?}, encountered def-id {:?} with no \
+ parent", did, item_def_id);
+ });
+ }
+ }
+ }
+ let mut generics = tcx.lookup_generics(item_def_id);
+ let mut path_def_id = did;
+ verbose = tcx.sess.verbose();
+ has_self = generics.has_self;
+
+ let mut child_types = 0;
+ if let Some(def_id) = generics.parent {
+ // Methods.
+ assert!(is_value_path);
+ child_types = generics.types.len();
+ generics = tcx.lookup_generics(def_id);
+ num_regions = generics.regions.len();
+ num_types = generics.types.len();
+
+ if has_self {
+ write!(f, "<{} as ", substs.type_at(0))?;
+ }
+
+ path_def_id = def_id;
+ } else {
+ item_name = None;
+
+ if is_value_path {
+ // Functions.
+ assert_eq!(has_self, false);
+ } else {
+ // Types and traits.
+ num_regions = generics.regions.len();
+ num_types = generics.types.len();
+ }
+ }
+
+ if !verbose {
+ if generics.types.last().map_or(false, |def| def.default.is_some()) {
+ if let Some(substs) = tcx.lift(&substs) {
+ let tps = substs.types().rev().skip(child_types);
+ for (def, actual) in generics.types.iter().rev().zip(tps) {
+ if def.default.subst(tcx, substs) != Some(actual) {
+ break;
+ }
+ num_supplied_defaults += 1;
+ }
+ }
+ }
+ }
+
+ write!(f, "{}", tcx.item_path_str(path_def_id))?;
+ Ok(tcx.lang_items.fn_trait_kind(path_def_id))
+ })?;
+
+ if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
+ let projection_ty = projections[0].ty;
+ if let TyTuple(ref args) = substs.type_at(1).sty {
+ return fn_sig(f, args, false, projection_ty);
+ }
}
-}
-pub fn bound_region_ptr_to_str(cx: ctxt, br: bound_region) -> ~str {
- bound_region_to_str(cx, "&", true, br)
-}
+ let empty = Cell::new(true);
+ let start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| {
+ if empty.get() {
+ empty.set(false);
+ write!(f, "{}", start)
+ } else {
+ write!(f, "{}", cont)
+ }
+ };
+
+ let print_regions = |f: &mut fmt::Formatter, start: &str, skip, count| {
+ // Don't print any regions if they're all erased.
+ let regions = || substs.regions().skip(skip).take(count);
+ if regions().all(|r: &ty::Region| *r == ty::ReErased) {
+ return Ok(());
+ }
-pub fn bound_region_to_str(cx: ctxt,
- prefix: &str, space: bool,
- br: bound_region) -> ~str {
- let space_str = if space { " " } else { "" };
+ for region in regions() {
+ let region: &ty::Region = region;
+ start_or_continue(f, start, ", ")?;
+ if verbose {
+ write!(f, "{:?}", region)?;
+ } else {
+ let s = region.to_string();
+ if s.is_empty() {
+ // This happens when the value of the region
+ // parameter is not easily serialized. This may be
+ // because the user omitted it in the first place,
+ // or because it refers to some block in the code,
+ // etc. I'm not sure how best to serialize this.
+ write!(f, "'_")?;
+ } else {
+ write!(f, "{}", s)?;
+ }
+ }
+ }
+
+ Ok(())
+ };
- if cx.sess.verbose() { return fmt!("%s%?%s", prefix, br, space_str); }
+ print_regions(f, "<", 0, num_regions)?;
- match br {
- br_named(id) => fmt!("%s'%s%s", prefix, cx.sess.str_of(id), space_str),
- br_self => fmt!("%s'self%s", prefix, space_str),
- br_anon(_) => prefix.to_str(),
- br_fresh(_) => prefix.to_str(),
- br_cap_avoid(_, br) => bound_region_to_str(cx, prefix, space, *br)
+ let tps = substs.types().take(num_types - num_supplied_defaults)
+ .skip(has_self as usize);
+
+ for ty in tps {
+ start_or_continue(f, "<", ", ")?;
+ write!(f, "{}", ty)?;
}
-}
-pub fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str {
- match cx.items.find(&node_id) {
- Some(&ast_map::node_block(ref blk)) => {
- fmt!("<block at %s>",
- cx.sess.codemap.span_to_str(blk.span))
- }
- Some(&ast_map::node_expr(expr)) => {
- match expr.node {
- ast::expr_call(*) => {
- fmt!("<call at %s>",
- cx.sess.codemap.span_to_str(expr.span))
- }
- ast::expr_match(*) => {
- fmt!("<match at %s>",
- cx.sess.codemap.span_to_str(expr.span))
- }
- ast::expr_assign_op(*) |
- ast::expr_unary(*) |
- ast::expr_binary(*) |
- ast::expr_index(*) => {
- fmt!("<method at %s>",
- cx.sess.codemap.span_to_str(expr.span))
- }
- _ => {
- fmt!("<expression at %s>",
- cx.sess.codemap.span_to_str(expr.span))
- }
+ for projection in projections {
+ start_or_continue(f, "<", ", ")?;
+ write!(f, "{}={}",
+ projection.projection_ty.item_name,
+ projection.ty)?;
+ }
+
+ start_or_continue(f, "", ">")?;
+
+ // For values, also print their name and type parameters.
+ if is_value_path {
+ empty.set(true);
+
+ if has_self {
+ write!(f, ">")?;
}
- }
- None => {
- fmt!("<unknown-%d>", node_id)
- }
- _ => { cx.sess.bug(
- fmt!("re_scope refers to %s",
- ast_map::node_id_to_str(cx.items, node_id,
- token::get_ident_interner()))) }
+
+ if let Some(item_name) = item_name {
+ write!(f, "::{}", item_name)?;
+ }
+
+ print_regions(f, "::<", num_regions, usize::MAX)?;
+
+ // FIXME: consider being smart with defaults here too
+ for ty in substs.types().skip(num_types) {
+ start_or_continue(f, "::<", ", ")?;
+ write!(f, "{}", ty)?;
+ }
+
+ start_or_continue(f, "", ">")?;
}
+
+ Ok(())
}
-// In general, if you are giving a region error message,
-// you should use `explain_region()` or, better yet,
-// `note_and_explain_region()`
-pub fn region_ptr_to_str(cx: ctxt, region: Region) -> ~str {
- region_to_str(cx, "&", true, region)
+fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ original: &ty::Binder<T>,
+ lifted: Option<ty::Binder<U>>) -> fmt::Result
+ where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx>
+{
+ // Replace any anonymous late-bound regions with named
+ // variants, using gensym'd identifiers, so that we can
+ // clearly differentiate between named and unnamed regions in
+ // the output. We'll probably want to tweak this over time to
+ // decide just how much information to give.
+ let value = if let Some(v) = lifted {
+ v
+ } else {
+ return write!(f, "{}", original.0);
+ };
+
+ let mut empty = true;
+ let mut start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| {
+ if empty {
+ empty = false;
+ write!(f, "{}", start)
+ } else {
+ write!(f, "{}", cont)
+ }
+ };
+
+ let new_value = tcx.replace_late_bound_regions(&value, |br| {
+ let _ = start_or_continue(f, "for<", ", ");
+ let br = match br {
+ ty::BrNamed(_, name, _) => {
+ let _ = write!(f, "{}", name);
+ br
+ }
+ ty::BrAnon(_) |
+ ty::BrFresh(_) |
+ ty::BrEnv => {
+ let name = token::intern("'r");
+ let _ = write!(f, "{}", name);
+ ty::BrNamed(tcx.map.local_def_id(CRATE_NODE_ID),
+ name,
+ ty::Issue32330::WontChange)
+ }
+ };
+ tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br))
+ }).0;
+
+ start_or_continue(f, "", "> ")?;
+ write!(f, "{}", new_value)
}
-pub fn region_to_str(cx: ctxt, prefix: &str, space: bool, region: Region) -> ~str {
- let space_str = if space { " " } else { "" };
+/// This curious type is here to help pretty-print trait objects. In
+/// a trait object, the projections are stored separately from the
+/// main trait bound, but in fact we want to package them together
+/// when printing out; they also have separate binders, but we want
+/// them to share a binder when we print them out. (And the binder
+/// pretty-printing logic is kind of clever and we don't want to
+/// reproduce it.) So we just repackage up the structure somewhat.
+///
+/// Right now there is only one trait in an object that can have
+/// projection bounds, so we just stuff them altogether. But in
+/// reality we should eventually sort things out better.
+#[derive(Clone, Debug)]
+struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>,
+ Vec<ty::ProjectionPredicate<'tcx>>);
+
+impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
+ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+ TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder))
+ }
+
+ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+ self.0.visit_with(visitor) || self.1.visit_with(visitor)
+ }
+}
- if cx.sess.verbose() {
- return fmt!("%s%?%s", prefix, region, space_str);
+impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let TraitAndProjections(ref trait_ref, ref projection_bounds) = *self;
+ parameterized(f, trait_ref.substs,
+ trait_ref.def_id,
+ projection_bounds)
}
+}
+
+impl<'tcx> fmt::Display for ty::TraitObject<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // Generate the main trait ref, including associated types.
+ ty::tls::with(|tcx| {
+ // Use a type that can't appear in defaults of type parameters.
+ let dummy_self = tcx.mk_infer(ty::FreshTy(0));
+
+ let principal = tcx.lift(&self.principal)
+ .expect("could not lift TraitRef for printing")
+ .with_self_ty(tcx, dummy_self).0;
+ let projections = self.projection_bounds.iter().map(|p| {
+ tcx.lift(p)
+ .expect("could not lift projection for printing")
+ .with_self_ty(tcx, dummy_self).0
+ }).collect();
+
+ let tap = ty::Binder(TraitAndProjections(principal, projections));
+ in_binder(f, tcx, &ty::Binder(""), Some(tap))
+ })?;
+
+ // Builtin bounds.
+ for bound in &self.builtin_bounds {
+ write!(f, " + {:?}", bound)?;
+ }
- // These printouts are concise. They do not contain all the information
- // the user might want to diagnose an error, but there is basically no way
- // to fit that into a short string. Hence the recommendation to use
- // `explain_region()` or `note_and_explain_region()`.
- match region {
- re_scope(_) => prefix.to_str(),
- re_bound(br) => bound_region_to_str(cx, prefix, space, br),
- re_free(ref fr) => bound_region_to_str(cx, prefix, space, fr.bound_region),
- re_infer(ReSkolemized(_, br)) => {
- bound_region_to_str(cx, prefix, space, br)
+ // FIXME: It'd be nice to compute from context when this bound
+ // is implied, but that's non-trivial -- we'd perhaps have to
+ // use thread-local data of some kind? There are also
+ // advantages to just showing the region, since it makes
+ // people aware that it's there.
+ let bound = self.region_bound.to_string();
+ if !bound.is_empty() {
+ write!(f, " + {}", bound)?;
}
- re_infer(ReVar(_)) => prefix.to_str(),
- re_static => fmt!("%s'static%s", prefix, space_str),
- re_empty => fmt!("%s'<empty>%s", prefix, space_str)
+
+ Ok(())
}
}
-fn mutability_to_str(m: ast::mutability) -> ~str {
- match m {
- ast::m_mutbl => ~"mut ",
- ast::m_imm => ~"",
- ast::m_const => ~"const "
+impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "TypeParameterDef({}, {:?}, {})",
+ self.name,
+ self.def_id,
+ self.index)
}
}
-pub fn mt_to_str(cx: ctxt, m: &mt) -> ~str {
- mt_to_str_wrapped(cx, "", m, "")
+impl<'tcx> fmt::Debug for ty::RegionParameterDef<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "RegionParameterDef({}, {:?}, {}, {:?})",
+ self.name,
+ self.def_id,
+ self.index,
+ self.bounds)
+ }
}
-pub fn mt_to_str_wrapped(cx: ctxt, before: &str, m: &mt, after: &str) -> ~str {
- let mstr = mutability_to_str(m.mutbl);
- return fmt!("%s%s%s%s", mstr, before, ty_to_str(cx, m.ty), after);
+impl<'tcx> fmt::Debug for ty::TyS<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", *self)
+ }
}
-pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
- match vs {
- ty::vstore_fixed(n) => fmt!("%u", n),
- ty::vstore_uniq => ~"~",
- ty::vstore_box => ~"@",
- ty::vstore_slice(r) => region_ptr_to_str(cx, r)
+impl<'tcx> fmt::Display for ty::TypeAndMut<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}{}",
+ if self.mutbl == hir::MutMutable { "mut " } else { "" },
+ self.ty)
}
}
-pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str {
- match s {
- ty::UniqTraitStore => ~"~",
- ty::BoxTraitStore => ~"@",
- ty::RegionTraitStore(r) => region_ptr_to_str(cx, r)
+impl<'tcx> fmt::Debug for ty::ItemSubsts<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ItemSubsts({:?})", self.substs)
}
}
-pub fn vstore_ty_to_str(cx: ctxt, mt: &mt, vs: ty::vstore) -> ~str {
- match vs {
- ty::vstore_fixed(_) => {
- fmt!("[%s, .. %s]", mt_to_str(cx, mt), vstore_to_str(cx, vs))
- }
- _ => {
- fmt!("%s%s", vstore_to_str(cx, vs), mt_to_str_wrapped(cx, "[", mt, "]"))
- }
+impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // 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.
+ write!(f, "<{:?} as {}>", self.self_ty(), *self)
}
}
-pub fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str {
- let tstrs = ts.map(|t| ty_to_str(cx, *t));
- fmt!("(%s)", tstrs.connect(", "))
+impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| {
+ let dummy_self = tcx.mk_infer(ty::FreshTy(0));
+
+ let trait_ref = tcx.lift(&ty::Binder(*self))
+ .expect("could not lift TraitRef for printing")
+ .with_self_ty(tcx, dummy_self).0;
+ parameterized(f, trait_ref.substs, trait_ref.def_id, &[])
+ })
+ }
}
-pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
- fmt!("fn%s -> %s",
- tys_to_str(cx, typ.inputs.map(|a| *a)),
- ty_to_str(cx, typ.output))
+impl<'tcx> fmt::Debug for ty::TraitDef<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "TraitDef(generics={:?}, trait_ref={:?})",
+ self.generics, self.trait_ref)
+ }
}
-pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str {
- trait_ref.user_string(cx)
+impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| {
+ write!(f, "{}", tcx.item_path_str(self.did))
+ })
+ }
}
-pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
- fn fn_input_to_str(cx: ctxt, input: ty::t) -> ~str {
- ty_to_str(cx, input)
+impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ty::adjustment::AdjustNeverToAny(ref target) => {
+ write!(f, "AdjustNeverToAny({:?})", target)
+ }
+ ty::adjustment::AdjustReifyFnPointer => {
+ write!(f, "AdjustReifyFnPointer")
+ }
+ ty::adjustment::AdjustUnsafeFnPointer => {
+ write!(f, "AdjustUnsafeFnPointer")
+ }
+ ty::adjustment::AdjustMutToConstPointer => {
+ write!(f, "AdjustMutToConstPointer")
+ }
+ ty::adjustment::AdjustDerefRef(ref data) => {
+ write!(f, "{:?}", data)
+ }
+ }
}
- fn bare_fn_to_str(cx: ctxt,
- purity: ast::purity,
- abis: AbiSet,
- ident: Option<ast::ident>,
- sig: &ty::FnSig)
- -> ~str {
- let mut s = ~"extern ";
+}
- s.push_str(abis.to_str());
- s.push_char(' ');
+impl<'tcx> fmt::Debug for ty::adjustment::AutoDerefRef<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "AutoDerefRef({}, unsize={:?}, {:?})",
+ self.autoderefs, self.unsize, self.autoref)
+ }
+}
- match purity {
- ast::impure_fn => {}
- _ => {
- s.push_str(purity.to_str());
- s.push_char(' ');
+impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut empty = true;
+ let mut maybe_continue = |f: &mut fmt::Formatter| {
+ if empty {
+ empty = false;
+ Ok(())
+ } else {
+ write!(f, " + ")
}
};
- s.push_str("fn");
+ maybe_continue(f)?;
+ write!(f, "{:?}", self.principal)?;
+
+ let region_str = format!("{:?}", self.region_bound);
+ if !region_str.is_empty() {
+ maybe_continue(f)?;
+ write!(f, "{}", region_str)?;
+ }
+
+ for bound in &self.builtin_bounds {
+ maybe_continue(f)?;
+ write!(f, "{:?}", bound)?;
+ }
- match ident {
- Some(i) => {
- s.push_char(' ');
- s.push_str(cx.sess.str_of(i));
- }
- _ => { }
+ for projection_bound in &self.projection_bounds {
+ maybe_continue(f)?;
+ write!(f, "{:?}", projection_bound)?;
}
- push_sig_to_str(cx, &mut s, sig);
+ Ok(())
+ }
+}
- return s;
+impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ty::Predicate::Trait(ref a) => write!(f, "{:?}", a),
+ ty::Predicate::Equate(ref pair) => write!(f, "{:?}", pair),
+ ty::Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
+ ty::Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
+ ty::Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
+ ty::Predicate::WellFormed(ty) => write!(f, "WF({:?})", ty),
+ ty::Predicate::ObjectSafe(trait_def_id) => {
+ write!(f, "ObjectSafe({:?})", trait_def_id)
+ }
+ ty::Predicate::ClosureKind(closure_def_id, kind) => {
+ write!(f, "ClosureKind({:?}, {:?})", closure_def_id, kind)
+ }
+ }
}
- fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str
- {
- let mut s = cty.sigil.to_str();
+}
+
+impl fmt::Display for ty::BoundRegion {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if verbose() {
+ return write!(f, "{:?}", *self);
+ }
- match (cty.sigil, cty.region) {
- (ast::ManagedSigil, ty::re_static) |
- (ast::OwnedSigil, ty::re_static) => {}
+ match *self {
+ BrNamed(_, name, _) => write!(f, "{}", name),
+ BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
+ }
+ }
+}
- (_, region) => {
- s.push_str(region_to_str(cx, "", true, region));
+impl fmt::Debug for ty::BoundRegion {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ BrAnon(n) => write!(f, "BrAnon({:?})", n),
+ BrFresh(n) => write!(f, "BrFresh({:?})", n),
+ BrNamed(did, name, issue32330) => {
+ write!(f, "BrNamed({:?}:{:?}, {:?}, {:?})",
+ did.krate, did.index, name, issue32330)
}
+ BrEnv => "BrEnv".fmt(f),
}
+ }
+}
- match cty.purity {
- ast::impure_fn => {}
- _ => {
- s.push_str(cty.purity.to_str());
- s.push_char(' ');
+impl fmt::Debug for ty::Region {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ty::ReEarlyBound(ref data) => {
+ write!(f, "ReEarlyBound({}, {})",
+ data.index,
+ data.name)
}
- };
- match cty.onceness {
- ast::Many => {}
- ast::Once => {
- s.push_str(cty.onceness.to_str());
- s.push_char(' ');
+ ty::ReLateBound(binder_id, ref bound_region) => {
+ write!(f, "ReLateBound({:?}, {:?})",
+ binder_id,
+ bound_region)
}
- };
- s.push_str("fn");
+ ty::ReFree(ref fr) => write!(f, "{:?}", fr),
- if !cty.bounds.is_empty() {
- s.push_str(":");
- }
- s.push_str(cty.bounds.repr(cx));
+ ty::ReScope(id) => {
+ write!(f, "ReScope({:?})", id)
+ }
- push_sig_to_str(cx, &mut s, &cty.sig);
+ ty::ReStatic => write!(f, "ReStatic"),
- return s;
- }
- fn push_sig_to_str(cx: ctxt, s: &mut ~str, sig: &ty::FnSig) {
- s.push_char('(');
- let strs = sig.inputs.map(|a| fn_input_to_str(cx, *a));
- s.push_str(strs.connect(", "));
- s.push_char(')');
- if ty::get(sig.output).sty != ty_nil {
- s.push_str(" -> ");
- if ty::type_is_bot(sig.output) {
- s.push_char('!');
- } else {
- s.push_str(ty_to_str(cx, sig.output));
- }
- }
- }
- fn method_to_str(cx: ctxt, m: ty::Method) -> ~str {
- bare_fn_to_str(cx,
- m.fty.purity,
- m.fty.abis,
- Some(m.ident),
- &m.fty.sig) + ";"
- }
- fn field_to_str(cx: ctxt, f: field) -> ~str {
- return fmt!("%s: %s", cx.sess.str_of(f.ident), mt_to_str(cx, &f.mt));
- }
-
- // if there is an id, print that instead of the structural type:
- /*for ty::type_def_id(typ).iter().advance |def_id| {
- // note that this typedef cannot have type parameters
- return ast_map::path_to_str(ty::item_path(cx, *def_id),
- cx.sess.intr());
- }*/
-
- // pretty print the structural type representation:
- return match ty::get(typ).sty {
- ty_nil => ~"()",
- ty_bot => ~"!",
- ty_bool => ~"bool",
- ty_int(ast::ty_i) => ~"int",
- ty_int(ast::ty_char) => ~"char",
- ty_int(t) => ast_util::int_ty_to_str(t),
- ty_uint(ast::ty_u) => ~"uint",
- ty_uint(t) => ast_util::uint_ty_to_str(t),
- ty_float(ast::ty_f) => ~"float",
- ty_float(t) => ast_util::float_ty_to_str(t),
- ty_box(ref tm) => ~"@" + mt_to_str(cx, tm),
- ty_uniq(ref tm) => ~"~" + mt_to_str(cx, tm),
- ty_ptr(ref tm) => ~"*" + mt_to_str(cx, tm),
- ty_rptr(r, ref tm) => {
- region_ptr_to_str(cx, r) + mt_to_str(cx, tm)
- }
- ty_unboxed_vec(ref tm) => { fmt!("unboxed_vec<%s>", mt_to_str(cx, tm)) }
- ty_type => ~"type",
- ty_tup(ref elems) => {
- let strs = elems.map(|elem| ty_to_str(cx, *elem));
- ~"(" + strs.connect(",") + ")"
- }
- ty_closure(ref f) => {
- closure_to_str(cx, f)
- }
- ty_bare_fn(ref f) => {
- bare_fn_to_str(cx, f.purity, f.abis, None, &f.sig)
- }
- ty_infer(infer_ty) => infer_ty.to_str(),
- ty_err => ~"[type error]",
- ty_param(param_ty {idx: id, def_id: did}) => {
- let mut parm = (('T' as uint) + id) as char;
- if (parm as uint) > ('Z' as uint) {
- parm = (parm as uint - 26) as char;
- }
-
- if cx.sess.verbose() {
- fmt!("%c:%?", parm, did)
- } else {
- fmt!("%c", parm)
- }
- }
- ty_self(*) => ~"Self",
- ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
- let path = ty::item_path(cx, did);
- let base = ast_map::path_to_str(path, cx.sess.intr());
- parameterized(cx, base, substs.self_r, substs.tps)
- }
- ty_trait(did, ref substs, s, mutbl, ref bounds) => {
- let path = ty::item_path(cx, did);
- let base = ast_map::path_to_str(path, cx.sess.intr());
- let ty = parameterized(cx, base, substs.self_r, substs.tps);
- let bound_sep = if bounds.is_empty() { "" } else { ":" };
- let bound_str = bounds.repr(cx);
- fmt!("%s%s%s%s%s", trait_store_to_str(cx, s), mutability_to_str(mutbl), ty,
- bound_sep, bound_str)
- }
- ty_evec(ref mt, vs) => {
- vstore_ty_to_str(cx, mt, vs)
- }
- ty_estr(vs) => fmt!("%s%s", vstore_to_str(cx, vs), "str"),
- ty_opaque_box => ~"@?",
- ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"&closure",
- ty_opaque_closure_ptr(ast::ManagedSigil) => ~"@closure",
- ty_opaque_closure_ptr(ast::OwnedSigil) => ~"~closure",
- }
-}
-
-pub fn parameterized(cx: ctxt,
- base: &str,
- self_r: Option<ty::Region>,
- tps: &[ty::t]) -> ~str {
-
- let mut strs = ~[];
- match self_r {
- None => (),
- Some(r) => {
- strs.push(region_to_str(cx, "", false, r))
+ ty::ReVar(ref vid) => {
+ write!(f, "{:?}", vid)
+ }
+
+ ty::ReSkolemized(id, ref bound_region) => {
+ write!(f, "ReSkolemized({}, {:?})", id.index, bound_region)
+ }
+
+ ty::ReEmpty => write!(f, "ReEmpty"),
+
+ ty::ReErased => write!(f, "ReErased")
}
- };
+ }
+}
- for tps.iter().advance |t| {
- strs.push(ty_to_str(cx, *t))
+impl<'tcx> fmt::Debug for ty::ClosureTy<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ClosureTy({},{:?},{})",
+ self.unsafety,
+ self.sig,
+ self.abi)
}
+}
- if strs.len() > 0u {
- fmt!("%s<%s>", base, strs.connect(","))
- } else {
- fmt!("%s", base)
+impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ClosureUpvar({:?},{:?})",
+ self.def,
+ self.ty)
}
}
-pub fn ty_to_short_str(cx: ctxt, typ: t) -> ~str {
- let mut s = encoder::encoded_ty(cx, typ);
- if s.len() >= 32u { s = s.slice(0u, 32u).to_owned(); }
- return s;
+impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ParameterEnvironment(\
+ free_substs={:?}, \
+ implicit_region_bound={:?}, \
+ caller_bounds={:?})",
+ self.free_substs,
+ self.implicit_region_bound,
+ self.caller_bounds)
+ }
}
-impl<T:Repr> Repr for Option<T> {
- fn repr(&self, tcx: ctxt) -> ~str {
- match self {
- &None => ~"None",
- &Some(ref t) => fmt!("Some(%s)", t.repr(tcx))
+impl<'tcx> fmt::Debug for ty::ObjectLifetimeDefault<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ty::ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"),
+ ty::ObjectLifetimeDefault::BaseDefault => write!(f, "BaseDefault"),
+ ty::ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r),
}
}
}
-/*
-Annoyingly, these conflict with @ast::expr.
+impl fmt::Display for ty::Region {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if verbose() {
+ return write!(f, "{:?}", *self);
+ }
-impl<T:Repr> Repr for @T {
- fn repr(&self, tcx: ctxt) -> ~str {
- (&**self).repr(tcx)
+ // These printouts are concise. They do not contain all the information
+ // the user might want to diagnose an error, but there is basically no way
+ // to fit that into a short string. Hence the recommendation to use
+ // `explain_region()` or `note_and_explain_region()`.
+ match *self {
+ ty::ReEarlyBound(ref data) => {
+ write!(f, "{}", data.name)
+ }
+ ty::ReLateBound(_, br) |
+ ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
+ ty::ReSkolemized(_, br) => {
+ write!(f, "{}", br)
+ }
+ ty::ReScope(_) |
+ ty::ReVar(_) |
+ ty::ReErased => Ok(()),
+ ty::ReStatic => write!(f, "'static"),
+ ty::ReEmpty => write!(f, "'<empty>"),
+ }
}
}
-impl<T:Repr> Repr for ~T {
- fn repr(&self, tcx: ctxt) -> ~str {
- (&**self).repr(tcx)
+impl fmt::Debug for ty::FreeRegion {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ReFree({:?}, {:?})",
+ self.scope, self.bound_region)
}
}
-*/
-fn repr_vec<T:Repr>(tcx: ctxt, v: &[T]) -> ~str {
- fmt!("[%s]", v.map(|t| t.repr(tcx)).connect(","))
+impl fmt::Debug for ty::Variance {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(match *self {
+ ty::Covariant => "+",
+ ty::Contravariant => "-",
+ ty::Invariant => "o",
+ ty::Bivariant => "*",
+ })
+ }
}
-impl<'self, T:Repr> Repr for &'self [T] {
- fn repr(&self, tcx: ctxt) -> ~str {
- repr_vec(tcx, *self)
+impl<'tcx> fmt::Debug for ty::GenericPredicates<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "GenericPredicates({:?})", self.predicates)
}
}
-// This is necessary to handle types like Option<@~[T]>, for which
-// autoderef cannot convert the &[T] handler
-impl<T:Repr> Repr for @~[T] {
- fn repr(&self, tcx: ctxt) -> ~str {
- repr_vec(tcx, **self)
+impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "InstantiatedPredicates({:?})",
+ self.predicates)
}
}
-impl Repr for ty::TypeParameterDef {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("TypeParameterDef {%?, bounds: %s}",
- self.def_id, self.bounds.repr(tcx))
+impl<'tcx> fmt::Debug for ty::ImplOrTraitItem<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ImplOrTraitItem(")?;
+ match *self {
+ ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i),
+ ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i),
+ ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i),
+ }?;
+ write!(f, ")")
}
}
-impl Repr for ty::t {
- fn repr(&self, tcx: ctxt) -> ~str {
- ty_to_str(tcx, *self)
+impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "fn")?;
+ fn_sig(f, &self.inputs, self.variadic, self.output)
}
}
-impl Repr for ty::substs {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("substs(self_r=%s, self_ty=%s, tps=%s)",
- self.self_r.repr(tcx),
- self.self_ty.repr(tcx),
- self.tps.repr(tcx))
+impl fmt::Display for ty::BuiltinBounds {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut bounds = self.iter();
+ if let Some(bound) = bounds.next() {
+ write!(f, "{:?}", bound)?;
+ for bound in bounds {
+ write!(f, " + {:?}", bound)?;
+ }
+ }
+ Ok(())
}
}
-impl Repr for ty::ParamBounds {
- fn repr(&self, tcx: ctxt) -> ~str {
- let mut res = ~[];
- for self.builtin_bounds.each |b| {
- res.push(match b {
- ty::BoundCopy => ~"Copy",
- ty::BoundStatic => ~"'static",
- ty::BoundSend => ~"Send",
- ty::BoundFreeze => ~"Freeze",
- ty::BoundSized => ~"Sized",
- });
- }
- for self.trait_bounds.iter().advance |t| {
- res.push(t.repr(tcx));
- }
- res.connect("+")
+impl fmt::Debug for ty::TyVid {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "_#{}t", self.index)
}
}
-impl Repr for ty::TraitRef {
- fn repr(&self, tcx: ctxt) -> ~str {
- trait_ref_to_str(tcx, self)
+impl fmt::Debug for ty::IntVid {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "_#{}i", self.index)
}
}
-impl Repr for @ast::expr {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("expr(%d: %s)",
- self.id,
- pprust::expr_to_str(*self, tcx.sess.intr()))
+impl fmt::Debug for ty::FloatVid {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "_#{}f", self.index)
}
}
-impl Repr for @ast::pat {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("pat(%d: %s)",
- self.id,
- pprust::pat_to_str(*self, tcx.sess.intr()))
+impl fmt::Debug for ty::RegionVid {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "'_#{}r", self.index)
}
}
-impl Repr for ty::Region {
- fn repr(&self, tcx: ctxt) -> ~str {
- region_to_str(tcx, "", false, *self)
+impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "({:?}; variadic: {})->{:?}", self.inputs, self.variadic, self.output)
}
}
-impl Repr for ast::def_id {
- fn repr(&self, tcx: ctxt) -> ~str {
- // Unfortunately, there seems to be no way to attempt to print
- // a path for a def-id, so I'll just make a best effort for now
- // and otherwise fallback to just printing the crate/node pair
- if self.crate == ast::local_crate {
- match tcx.items.find(&self.node) {
- Some(&ast_map::node_item(*)) |
- Some(&ast_map::node_foreign_item(*)) |
- Some(&ast_map::node_method(*)) |
- Some(&ast_map::node_trait_method(*)) |
- Some(&ast_map::node_variant(*)) |
- Some(&ast_map::node_struct_ctor(*)) => {
- return fmt!("%?:%s", *self, ty::item_path_str(tcx, *self));
- }
- _ => {}
- }
+impl fmt::Debug for ty::InferTy {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ty::TyVar(ref v) => v.fmt(f),
+ ty::IntVar(ref v) => v.fmt(f),
+ ty::FloatVar(ref v) => v.fmt(f),
+ ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
+ ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
+ ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
}
- return fmt!("%?", *self);
}
}
-impl Repr for ty::ty_param_bounds_and_ty {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("ty_param_bounds_and_ty {generics: %s, ty: %s}",
- self.generics.repr(tcx),
- self.ty.repr(tcx))
+impl fmt::Debug for ty::IntVarValue {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ty::IntType(ref v) => v.fmt(f),
+ ty::UintType(ref v) => v.fmt(f),
+ }
}
}
-impl Repr for ty::Generics {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("Generics {type_param_defs: %s, region_param: %?}",
- self.type_param_defs.repr(tcx),
- self.region_param)
+// The generic impl doesn't work yet because projections are not
+// normalized under HRTB.
+/*impl<T> fmt::Display for ty::Binder<T>
+ where T: fmt::Display + for<'a> ty::Lift<'a>,
+ for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
}
-}
+}*/
-impl Repr for ty::Method {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("method {ident: %s, generics: %s, transformed_self_ty: %s, \
- fty: %s, explicit_self: %s, vis: %s, def_id: %s}",
- self.ident.repr(tcx),
- self.generics.repr(tcx),
- self.transformed_self_ty.repr(tcx),
- self.fty.repr(tcx),
- self.explicit_self.repr(tcx),
- self.vis.repr(tcx),
- self.def_id.repr(tcx))
+impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
}
}
-impl Repr for ast::ident {
- fn repr(&self, _tcx: ctxt) -> ~str {
- token::ident_to_str(self).to_owned()
+impl<'tcx> fmt::Display for ty::Binder<ty::TraitPredicate<'tcx>> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
}
}
-impl Repr for ast::explicit_self_ {
- fn repr(&self, _tcx: ctxt) -> ~str {
- fmt!("%?", *self)
+impl<'tcx> fmt::Display for ty::Binder<ty::EquatePredicate<'tcx>> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
}
}
-impl Repr for ast::visibility {
- fn repr(&self, _tcx: ctxt) -> ~str {
- fmt!("%?", *self)
+impl<'tcx> fmt::Display for ty::Binder<ty::ProjectionPredicate<'tcx>> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
}
}
-impl Repr for ty::BareFnTy {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("BareFnTy {purity: %?, abis: %s, sig: %s}",
- self.purity,
- self.abis.to_str(),
- self.sig.repr(tcx))
+impl<'tcx> fmt::Display for ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, &'tcx ty::Region>> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
}
}
-impl Repr for ty::FnSig {
- fn repr(&self, tcx: ctxt) -> ~str {
- fn_sig_to_str(tcx, self)
+impl<'tcx> fmt::Display for ty::Binder<ty::OutlivesPredicate<&'tcx ty::Region,
+ &'tcx ty::Region>> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
}
}
-impl Repr for typeck::method_map_entry {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("method_map_entry {self_arg: %s, \
- explicit_self: %s, \
- origin: %s}",
- self.self_ty.repr(tcx),
- self.explicit_self.repr(tcx),
- self.origin.repr(tcx))
+impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ parameterized(f, self.substs, self.def_id, &[])
}
}
-impl Repr for typeck::method_origin {
- fn repr(&self, tcx: ctxt) -> ~str {
- match self {
- &typeck::method_super(def_id, n) => {
- fmt!("method_super(%s, %?)",
- def_id.repr(tcx), n)
+impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ TyBool => write!(f, "bool"),
+ TyChar => write!(f, "char"),
+ TyInt(t) => write!(f, "{}", t.ty_to_string()),
+ TyUint(t) => write!(f, "{}", t.ty_to_string()),
+ TyFloat(t) => write!(f, "{}", t.ty_to_string()),
+ TyBox(typ) => write!(f, "Box<{}>", typ),
+ TyRawPtr(ref tm) => {
+ write!(f, "*{} {}", match tm.mutbl {
+ hir::MutMutable => "mut",
+ hir::MutImmutable => "const",
+ }, tm.ty)
}
- &typeck::method_static(def_id) => {
- fmt!("method_static(%s)", def_id.repr(tcx))
+ TyRef(r, ref tm) => {
+ write!(f, "&")?;
+ let s = r.to_string();
+ write!(f, "{}", s)?;
+ if !s.is_empty() {
+ write!(f, " ")?;
+ }
+ write!(f, "{}", tm)
+ }
+ TyNever => write!(f, "!"),
+ TyTuple(ref tys) => {
+ write!(f, "(")?;
+ let mut tys = tys.iter();
+ if let Some(&ty) = tys.next() {
+ write!(f, "{},", ty)?;
+ if let Some(&ty) = tys.next() {
+ write!(f, " {}", ty)?;
+ for &ty in tys {
+ write!(f, ", {}", ty)?;
+ }
+ }
+ }
+ write!(f, ")")
+ }
+ TyFnDef(def_id, substs, ref bare_fn) => {
+ if bare_fn.unsafety == hir::Unsafety::Unsafe {
+ write!(f, "unsafe ")?;
+ }
+
+ if bare_fn.abi != Abi::Rust {
+ write!(f, "extern {} ", bare_fn.abi)?;
+ }
+
+ write!(f, "{} {{", bare_fn.sig.0)?;
+ parameterized(f, substs, def_id, &[])?;
+ write!(f, "}}")
}
- &typeck::method_param(ref p) => {
- p.repr(tcx)
+ TyFnPtr(ref bare_fn) => {
+ if bare_fn.unsafety == hir::Unsafety::Unsafe {
+ write!(f, "unsafe ")?;
+ }
+
+ if bare_fn.abi != Abi::Rust {
+ write!(f, "extern {} ", bare_fn.abi)?;
+ }
+
+ write!(f, "{}", bare_fn.sig.0)
}
- &typeck::method_trait(def_id, n, st) => {
- fmt!("method_trait(%s, %?, %s)", def_id.repr(tcx), n,
- st.repr(tcx))
+ TyInfer(infer_ty) => write!(f, "{}", infer_ty),
+ TyError => write!(f, "[type error]"),
+ TyParam(ref param_ty) => write!(f, "{}", param_ty),
+ TyAdt(def, substs) => {
+ ty::tls::with(|tcx| {
+ if def.did.is_local() &&
+ !tcx.tcache.borrow().contains_key(&def.did) {
+ write!(f, "{}<..>", tcx.item_path_str(def.did))
+ } else {
+ parameterized(f, substs, def.did, &[])
+ }
+ })
}
- &typeck::method_self(def_id, n) => {
- fmt!("method_self(%s, %?)", def_id.repr(tcx), n)
+ TyTrait(ref data) => write!(f, "{}", data),
+ ty::TyProjection(ref data) => write!(f, "{}", data),
+ ty::TyAnon(def_id, substs) => {
+ ty::tls::with(|tcx| {
+ // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
+ // by looking up the projections associated with the def_id.
+ let item_predicates = tcx.lookup_predicates(def_id);
+ let substs = tcx.lift(&substs).unwrap_or_else(|| {
+ Substs::empty(tcx)
+ });
+ let bounds = item_predicates.instantiate(tcx, substs);
+
+ let mut first = true;
+ let mut is_sized = false;
+ write!(f, "impl")?;
+ for predicate in bounds.predicates {
+ if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
+ // Don't print +Sized, but rather +?Sized if absent.
+ if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() {
+ is_sized = true;
+ continue;
+ }
+
+ write!(f, "{}{}", if first { " " } else { "+" }, trait_ref)?;
+ first = false;
+ }
+ }
+ if !is_sized {
+ write!(f, "{}?Sized", if first { " " } else { "+" })?;
+ }
+ Ok(())
+ })
}
+ TyStr => write!(f, "str"),
+ TyClosure(did, substs) => ty::tls::with(|tcx| {
+ write!(f, "[closure")?;
+
+ if let Some(node_id) = tcx.map.as_local_node_id(did) {
+ write!(f, "@{:?}", tcx.map.span(node_id))?;
+ let mut sep = " ";
+ tcx.with_freevars(node_id, |freevars| {
+ for (freevar, upvar_ty) in freevars.iter().zip(substs.upvar_tys) {
+ let def_id = freevar.def.def_id();
+ let node_id = tcx.map.as_local_node_id(def_id).unwrap();
+ write!(f,
+ "{}{}:{}",
+ sep,
+ tcx.local_var_name_str(node_id),
+ upvar_ty)?;
+ sep = ", ";
+ }
+ Ok(())
+ })?
+ } else {
+ // cross-crate closure types should only be
+ // visible in trans bug reports, I imagine.
+ write!(f, "@{:?}", did)?;
+ let mut sep = " ";
+ for (index, upvar_ty) in substs.upvar_tys.iter().enumerate() {
+ write!(f, "{}{}:{}", sep, index, upvar_ty)?;
+ sep = ", ";
+ }
+ }
+
+ write!(f, "]")
+ }),
+ TyArray(ty, sz) => write!(f, "[{}; {}]", ty, sz),
+ TySlice(ty) => write!(f, "[{}]", ty)
}
}
}
-impl Repr for typeck::method_param {
- fn repr(&self, tcx: ctxt) -> ~str {
- fmt!("method_param(%s,%?,%?,%?)",
- self.trait_id.repr(tcx),
- self.method_num,
- self.param_num,
- self.bound_num)
+impl<'tcx> fmt::Display for ty::TyS<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.sty)
}
}
-impl Repr for ty::TraitStore {
- fn repr(&self, tcx: ctxt) -> ~str {
- match self {
- &ty::BoxTraitStore => ~"@Trait",
- &ty::UniqTraitStore => ~"~Trait",
- &ty::RegionTraitStore(r) => fmt!("&%s Trait", r.repr(tcx))
- }
+impl fmt::Debug for ty::UpvarId {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "UpvarId({};`{}`;{})",
+ self.var_id,
+ ty::tls::with(|tcx| tcx.local_var_name_str(self.var_id)),
+ self.closure_expr_id)
}
}
-impl Repr for ty::vstore {
- fn repr(&self, tcx: ctxt) -> ~str {
- vstore_to_str(tcx, *self)
+impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "UpvarBorrow({:?}, {:?})",
+ self.kind, self.region)
}
}
-impl Repr for ast_map::path_elt {
- fn repr(&self, tcx: ctxt) -> ~str {
+impl fmt::Display for ty::InferTy {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let print_var_ids = verbose();
match *self {
- ast_map::path_mod(id) => id.repr(tcx),
- ast_map::path_name(id) => id.repr(tcx)
+ ty::TyVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
+ ty::IntVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
+ ty::FloatVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
+ ty::TyVar(_) => write!(f, "_"),
+ ty::IntVar(_) => write!(f, "{}", "{integer}"),
+ ty::FloatVar(_) => write!(f, "{}", "{float}"),
+ ty::FreshTy(v) => write!(f, "FreshTy({})", v),
+ ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
+ ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
}
}
}
-impl Repr for ty::BuiltinBound {
- fn repr(&self, _tcx: ctxt) -> ~str {
- fmt!("%?", *self)
+impl<'tcx> fmt::Display for ty::ExplicitSelfCategory<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str(match *self {
+ ty::ExplicitSelfCategory::Static => "static",
+ ty::ExplicitSelfCategory::ByValue => "self",
+ ty::ExplicitSelfCategory::ByReference(_, hir::MutMutable) => {
+ "&mut self"
+ }
+ ty::ExplicitSelfCategory::ByReference(_, hir::MutImmutable) => "&self",
+ ty::ExplicitSelfCategory::ByBox => "Box<self>",
+ })
}
}
-impl UserString for ty::BuiltinBound {
- fn user_string(&self, _tcx: ctxt) -> ~str {
- match *self {
- ty::BoundCopy => ~"Copy",
- ty::BoundStatic => ~"'static",
- ty::BoundSend => ~"Send",
- ty::BoundFreeze => ~"Freeze",
- ty::BoundSized => ~"Sized",
- }
+impl fmt::Display for ty::ParamTy {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.name)
}
}
-impl Repr for ty::BuiltinBounds {
- fn repr(&self, tcx: ctxt) -> ~str {
- self.user_string(tcx)
+impl fmt::Debug for ty::ParamTy {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}/#{}", self, self.idx)
}
}
-impl UserString for ty::BuiltinBounds {
- fn user_string(&self, tcx: ctxt) -> ~str {
- if self.is_empty() { ~"<no-bounds>" } else {
- let mut result = ~[];
- for self.each |bb| {
- result.push(bb.user_string(tcx));
- }
- result.connect("+")
- }
+impl<'tcx, T, U> fmt::Display for ty::OutlivesPredicate<T,U>
+ where T: fmt::Display, U: fmt::Display
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} : {}", self.0, self.1)
}
}
-impl UserString for ty::TraitRef {
- fn user_string(&self, tcx: ctxt) -> ~str {
- let path = ty::item_path(tcx, self.def_id);
- let base = ast_map::path_to_str(path, tcx.sess.intr());
- if tcx.sess.verbose() && self.substs.self_ty.is_some() {
- let mut all_tps = copy self.substs.tps;
- for self.substs.self_ty.iter().advance |&t| { all_tps.push(t); }
- parameterized(tcx, base, self.substs.self_r, all_tps)
- } else {
- parameterized(tcx, base, self.substs.self_r,
- self.substs.tps)
+impl<'tcx> fmt::Display for ty::EquatePredicate<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} == {}", self.0, self.1)
+ }
+}
+
+impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "TraitPredicate({:?})",
+ self.trait_ref)
+ }
+}
+
+impl<'tcx> fmt::Display for ty::TraitPredicate<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}: {}", self.trait_ref.self_ty(), self.trait_ref)
+ }
+}
+
+impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "ProjectionPredicate({:?}, {:?})",
+ self.projection_ty,
+ self.ty)
+ }
+}
+
+impl<'tcx> fmt::Display for ty::ProjectionPredicate<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} == {}",
+ self.projection_ty,
+ self.ty)
+ }
+}
+
+impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}::{}",
+ self.trait_ref,
+ self.item_name)
+ }
+}
+
+impl fmt::Display for ty::ClosureKind {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ty::ClosureKind::Fn => write!(f, "Fn"),
+ ty::ClosureKind::FnMut => write!(f, "FnMut"),
+ ty::ClosureKind::FnOnce => write!(f, "FnOnce"),
}
}
}
-impl UserString for ty::t {
- fn user_string(&self, tcx: ctxt) -> ~str {
- ty_to_str(tcx, *self)
+impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ ty::Predicate::Trait(ref data) => write!(f, "{}", data),
+ ty::Predicate::Equate(ref predicate) => write!(f, "{}", predicate),
+ ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
+ ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),
+ ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate),
+ ty::Predicate::WellFormed(ty) => write!(f, "{} well-formed", ty),
+ ty::Predicate::ObjectSafe(trait_def_id) =>
+ ty::tls::with(|tcx| {
+ write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
+ }),
+ ty::Predicate::ClosureKind(closure_def_id, kind) =>
+ ty::tls::with(|tcx| {
+ write!(f, "the closure `{}` implements the trait `{}`",
+ tcx.item_path_str(closure_def_id), kind)
+ }),
+ }
}
}