]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
auto merge of #13049 : alexcrichton/rust/io-fill, r=huonw
[rust.git] / src / librustc / util / ppaux.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 use metadata::encoder;
13 use middle::ty::{ReSkolemized, ReVar};
14 use middle::ty::{BoundRegion, BrAnon, BrNamed};
15 use middle::ty::{BrFresh, ctxt};
16 use middle::ty::{mt, t, param_ty};
17 use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region,
18                  ReEmpty};
19 use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
20 use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
21 use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_self, ty_tup};
22 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_unboxed_vec, ty_infer};
23 use middle::ty;
24 use middle::typeck;
25
26 use syntax::abi::AbiSet;
27 use syntax::ast_map;
28 use syntax::codemap::{Span, Pos};
29 use syntax::parse::token;
30 use syntax::print::pprust;
31 use syntax::{ast, ast_util};
32 use syntax::owned_slice::OwnedSlice;
33
34 /// Produces a string suitable for debugging output.
35 pub trait Repr {
36     fn repr(&self, tcx: &ctxt) -> ~str;
37 }
38
39 /// Produces a string suitable for showing to the user.
40 pub trait UserString {
41     fn user_string(&self, tcx: &ctxt) -> ~str;
42 }
43
44 pub fn note_and_explain_region(cx: &ctxt,
45                                prefix: &str,
46                                region: ty::Region,
47                                suffix: &str) {
48     match explain_region_and_span(cx, region) {
49       (ref str, Some(span)) => {
50         cx.sess.span_note(
51             span,
52             format!("{}{}{}", prefix, *str, suffix));
53       }
54       (ref str, None) => {
55         cx.sess.note(
56             format!("{}{}{}", prefix, *str, suffix));
57       }
58     }
59 }
60
61 /// Returns a string like "the block at 27:31" that attempts to explain a
62 /// lifetime in a way it might plausibly be understood.
63 pub fn explain_region(cx: &ctxt, region: ty::Region) -> ~str {
64   let (res, _) = explain_region_and_span(cx, region);
65   return res;
66 }
67
68
69 pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
70                             -> (~str, Option<Span>) {
71     return match region {
72       ReScope(node_id) => {
73         match cx.map.find(node_id) {
74           Some(ast_map::NodeBlock(ref blk)) => {
75             explain_span(cx, "block", blk.span)
76           }
77           Some(ast_map::NodeExpr(expr)) => {
78             match expr.node {
79               ast::ExprCall(..) => explain_span(cx, "call", expr.span),
80               ast::ExprMethodCall(..) => {
81                 explain_span(cx, "method call", expr.span)
82               },
83               ast::ExprMatch(..) => explain_span(cx, "match", expr.span),
84               _ => explain_span(cx, "expression", expr.span)
85             }
86           }
87           Some(ast_map::NodeStmt(stmt)) => {
88               explain_span(cx, "statement", stmt.span)
89           }
90           Some(ast_map::NodeItem(it)) if (match it.node {
91                 ast::ItemFn(..) => true, _ => false}) => {
92               explain_span(cx, "function body", it.span)
93           }
94           Some(_) | None => {
95             // this really should not happen
96             (format!("unknown scope: {}.  Please report a bug.", node_id),
97              None)
98           }
99         }
100       }
101
102       ReFree(ref fr) => {
103         let prefix = match fr.bound_region {
104           BrAnon(idx) => format!("the anonymous lifetime \\#{} defined on",
105                                idx + 1),
106           BrFresh(_) => format!("an anonymous lifetime defined on"),
107           _ => format!("the lifetime {} as defined on",
108                     bound_region_ptr_to_str(cx, fr.bound_region))
109         };
110
111         match cx.map.find(fr.scope_id) {
112           Some(ast_map::NodeBlock(ref blk)) => {
113             let (msg, opt_span) = explain_span(cx, "block", blk.span);
114             (format!("{} {}", prefix, msg), opt_span)
115           }
116           Some(ast_map::NodeItem(it)) if match it.node {
117                 ast::ItemImpl(..) => true, _ => false} => {
118             let (msg, opt_span) = explain_span(cx, "impl", it.span);
119             (format!("{} {}", prefix, msg), opt_span)
120           }
121           Some(_) | None => {
122             // this really should not happen
123             (format!("{} node {}", prefix, fr.scope_id), None)
124           }
125         }
126       }
127
128       ReStatic => { (~"the static lifetime", None) }
129
130       ReEmpty => { (~"the empty lifetime", None) }
131
132       // I believe these cases should not occur (except when debugging,
133       // perhaps)
134       ty::ReInfer(_) | ty::ReEarlyBound(..) | ty::ReLateBound(..) => {
135         (format!("lifetime {:?}", region), None)
136       }
137     };
138
139     fn explain_span(cx: &ctxt, heading: &str, span: Span)
140         -> (~str, Option<Span>) {
141         let lo = cx.sess.codemap().lookup_char_pos_adj(span.lo);
142         (format!("the {} at {}:{}", heading,
143               lo.line, lo.col.to_uint()), Some(span))
144     }
145 }
146
147 pub fn bound_region_ptr_to_str(cx: &ctxt, br: BoundRegion) -> ~str {
148     bound_region_to_str(cx, "&", true, br)
149 }
150
151 pub fn bound_region_to_str(cx: &ctxt,
152                            prefix: &str, space: bool,
153                            br: BoundRegion) -> ~str {
154     let space_str = if space { " " } else { "" };
155
156     if cx.sess.verbose() {
157         return format!("{}{}{}", prefix, br.repr(cx), space_str);
158     }
159
160     match br {
161         BrNamed(_, name)   => format!("{}'{}{}", prefix,
162                                       token::get_name(name), space_str),
163         BrAnon(_)           => prefix.to_str(),
164         BrFresh(_)          => prefix.to_str(),
165     }
166 }
167
168 pub fn ReScope_id_to_str(cx: &ctxt, node_id: ast::NodeId) -> ~str {
169     match cx.map.find(node_id) {
170       Some(ast_map::NodeBlock(ref blk)) => {
171         format!("<block at {}>",
172              cx.sess.codemap().span_to_str(blk.span))
173       }
174       Some(ast_map::NodeExpr(expr)) => {
175         match expr.node {
176           ast::ExprCall(..) => {
177             format!("<call at {}>",
178                  cx.sess.codemap().span_to_str(expr.span))
179           }
180           ast::ExprMatch(..) => {
181             format!("<match at {}>",
182                  cx.sess.codemap().span_to_str(expr.span))
183           }
184           ast::ExprAssignOp(..) |
185           ast::ExprUnary(..) |
186           ast::ExprBinary(..) |
187           ast::ExprIndex(..) => {
188             format!("<method at {}>",
189                  cx.sess.codemap().span_to_str(expr.span))
190           }
191           _ => {
192             format!("<expression at {}>",
193                  cx.sess.codemap().span_to_str(expr.span))
194           }
195         }
196       }
197       None => {
198         format!("<unknown-{}>", node_id)
199       }
200       _ => cx.sess.bug(format!("ReScope refers to {}", cx.map.node_to_str(node_id)))
201     }
202 }
203
204 // In general, if you are giving a region error message,
205 // you should use `explain_region()` or, better yet,
206 // `note_and_explain_region()`
207 pub fn region_ptr_to_str(cx: &ctxt, region: Region) -> ~str {
208     region_to_str(cx, "&", true, region)
209 }
210
211 pub fn region_to_str(cx: &ctxt, prefix: &str, space: bool, region: Region) -> ~str {
212     let space_str = if space { " " } else { "" };
213
214     if cx.sess.verbose() {
215         return format!("{}{}{}", prefix, region.repr(cx), space_str);
216     }
217
218     // These printouts are concise.  They do not contain all the information
219     // the user might want to diagnose an error, but there is basically no way
220     // to fit that into a short string.  Hence the recommendation to use
221     // `explain_region()` or `note_and_explain_region()`.
222     match region {
223         ty::ReScope(_) => prefix.to_str(),
224         ty::ReEarlyBound(_, _, name) => token::get_name(name).get().to_str(),
225         ty::ReLateBound(_, br) => bound_region_to_str(cx, prefix, space, br),
226         ty::ReFree(ref fr) => bound_region_to_str(cx, prefix, space, fr.bound_region),
227         ty::ReInfer(ReSkolemized(_, br)) => {
228             bound_region_to_str(cx, prefix, space, br)
229         }
230         ty::ReInfer(ReVar(_)) => prefix.to_str(),
231         ty::ReStatic => format!("{}'static{}", prefix, space_str),
232         ty::ReEmpty => format!("{}'<empty>{}", prefix, space_str)
233     }
234 }
235
236 pub fn mutability_to_str(m: ast::Mutability) -> ~str {
237     match m {
238         ast::MutMutable => ~"mut ",
239         ast::MutImmutable => ~"",
240     }
241 }
242
243 pub fn mt_to_str(cx: &ctxt, m: &mt) -> ~str {
244     mt_to_str_wrapped(cx, "", m, "")
245 }
246
247 pub fn mt_to_str_wrapped(cx: &ctxt, before: &str, m: &mt, after: &str) -> ~str {
248     let mstr = mutability_to_str(m.mutbl);
249     return format!("{}{}{}{}", mstr, before, ty_to_str(cx, m.ty), after);
250 }
251
252 pub fn vstore_to_str(cx: &ctxt, vs: ty::vstore) -> ~str {
253     match vs {
254       ty::vstore_fixed(n) => format!("{}", n),
255       ty::vstore_uniq => ~"~",
256       ty::vstore_slice(r) => region_ptr_to_str(cx, r)
257     }
258 }
259
260 pub fn trait_store_to_str(cx: &ctxt, s: ty::TraitStore) -> ~str {
261     match s {
262       ty::UniqTraitStore => ~"~",
263       ty::RegionTraitStore(r) => region_ptr_to_str(cx, r)
264     }
265 }
266
267 pub fn vstore_ty_to_str(cx: &ctxt, mt: &mt, vs: ty::vstore) -> ~str {
268     match vs {
269         ty::vstore_fixed(_) => {
270             format!("[{}, .. {}]", mt_to_str(cx, mt), vstore_to_str(cx, vs))
271         }
272         _ => {
273             format!("{}{}", vstore_to_str(cx, vs), mt_to_str_wrapped(cx, "[", mt, "]"))
274         }
275     }
276 }
277
278 pub fn vec_map_to_str<T>(ts: &[T], f: |t: &T| -> ~str) -> ~str {
279     let tstrs = ts.map(f);
280     format!("[{}]", tstrs.connect(", "))
281 }
282
283 pub fn tys_to_str(cx: &ctxt, ts: &[t]) -> ~str {
284     vec_map_to_str(ts, |t| ty_to_str(cx, *t))
285 }
286
287 pub fn fn_sig_to_str(cx: &ctxt, typ: &ty::FnSig) -> ~str {
288     format!("fn{}{} -> {}",
289             typ.binder_id,
290             typ.inputs.repr(cx),
291             typ.output.repr(cx))
292 }
293
294 pub fn trait_ref_to_str(cx: &ctxt, trait_ref: &ty::TraitRef) -> ~str {
295     trait_ref.user_string(cx)
296 }
297
298 pub fn ty_to_str(cx: &ctxt, typ: t) -> ~str {
299     fn fn_input_to_str(cx: &ctxt, input: ty::t) -> ~str {
300         ty_to_str(cx, input)
301     }
302     fn bare_fn_to_str(cx: &ctxt,
303                       purity: ast::Purity,
304                       abis: AbiSet,
305                       ident: Option<ast::Ident>,
306                       sig: &ty::FnSig)
307                       -> ~str {
308         let mut s = if abis.is_rust() {
309             ~""
310         } else {
311             format!("extern {} ", abis.to_str())
312         };
313
314         match purity {
315             ast::ImpureFn => {}
316             _ => {
317                 s.push_str(purity.to_str());
318                 s.push_char(' ');
319             }
320         };
321
322         s.push_str("fn");
323
324         match ident {
325             Some(i) => {
326                 s.push_char(' ');
327                 s.push_str(token::get_ident(i).get());
328             }
329             _ => { }
330         }
331
332         push_sig_to_str(cx, &mut s, '(', ')', sig);
333
334         return s;
335     }
336     fn closure_to_str(cx: &ctxt, cty: &ty::ClosureTy) -> ~str {
337         let is_proc =
338             (cty.sigil, cty.onceness) == (ast::OwnedSigil, ast::Once);
339         let is_borrowed_closure = cty.sigil == ast::BorrowedSigil;
340
341         let mut s = if is_proc || is_borrowed_closure {
342             ~""
343         } else {
344             cty.sigil.to_str()
345         };
346
347         match (cty.sigil, cty.region) {
348             (ast::ManagedSigil, ty::ReStatic) |
349             (ast::OwnedSigil, ty::ReStatic) => {}
350
351             (_, region) => {
352                 s.push_str(region_to_str(cx, "", true, region));
353             }
354         }
355
356         match cty.purity {
357             ast::ImpureFn => {}
358             _ => {
359                 s.push_str(cty.purity.to_str());
360                 s.push_char(' ');
361             }
362         };
363
364         if is_proc {
365             s.push_str("proc");
366         } else {
367             match cty.onceness {
368                 ast::Many => {}
369                 ast::Once => {
370                     s.push_str(cty.onceness.to_str());
371                     s.push_char(' ');
372                 }
373             };
374
375             if !is_borrowed_closure {
376                 s.push_str("fn");
377             }
378         }
379
380         if !is_borrowed_closure {
381             // Print bounds before `fn` if this is not a borrowed closure.
382             if !cty.bounds.is_empty() {
383                 s.push_str(":");
384                 s.push_str(cty.bounds.repr(cx));
385             }
386
387             push_sig_to_str(cx, &mut s, '(', ')', &cty.sig);
388         } else {
389             // Print bounds after the signature if this is a borrowed closure.
390             push_sig_to_str(cx, &mut s, '|', '|', &cty.sig);
391
392             if is_borrowed_closure {
393                 if !cty.bounds.is_empty() {
394                     s.push_str(":");
395                     s.push_str(cty.bounds.repr(cx));
396                 }
397             }
398         }
399
400         return s;
401     }
402     fn push_sig_to_str(cx: &ctxt,
403                        s: &mut ~str,
404                        bra: char,
405                        ket: char,
406                        sig: &ty::FnSig) {
407         s.push_char(bra);
408         let strs = sig.inputs.map(|a| fn_input_to_str(cx, *a));
409         s.push_str(strs.connect(", "));
410         if sig.variadic {
411             s.push_str(", ...");
412         }
413         s.push_char(ket);
414
415         if ty::get(sig.output).sty != ty_nil {
416             s.push_str(" -> ");
417             if ty::type_is_bot(sig.output) {
418                 s.push_char('!');
419             } else {
420                 s.push_str(ty_to_str(cx, sig.output));
421             }
422         }
423     }
424
425     // if there is an id, print that instead of the structural type:
426     /*for def_id in ty::type_def_id(typ).iter() {
427         // note that this typedef cannot have type parameters
428         return ty::item_path_str(cx, *def_id);
429     }*/
430
431     // pretty print the structural type representation:
432     return match ty::get(typ).sty {
433       ty_nil => ~"()",
434       ty_bot => ~"!",
435       ty_bool => ~"bool",
436       ty_char => ~"char",
437       ty_int(ast::TyI) => ~"int",
438       ty_int(t) => ast_util::int_ty_to_str(t),
439       ty_uint(ast::TyU) => ~"uint",
440       ty_uint(t) => ast_util::uint_ty_to_str(t),
441       ty_float(t) => ast_util::float_ty_to_str(t),
442       ty_box(typ) => ~"@" + ty_to_str(cx, typ),
443       ty_uniq(typ) => ~"~" + ty_to_str(cx, typ),
444       ty_ptr(ref tm) => ~"*" + mt_to_str(cx, tm),
445       ty_rptr(r, ref tm) => {
446         region_ptr_to_str(cx, r) + mt_to_str(cx, tm)
447       }
448       ty_unboxed_vec(ref tm) => { format!("unboxed_vec<{}>", mt_to_str(cx, tm)) }
449       ty_tup(ref elems) => {
450         let strs = elems.map(|elem| ty_to_str(cx, *elem));
451         ~"(" + strs.connect(",") + ")"
452       }
453       ty_closure(ref f) => {
454           closure_to_str(cx, *f)
455       }
456       ty_bare_fn(ref f) => {
457           bare_fn_to_str(cx, f.purity, f.abis, None, &f.sig)
458       }
459       ty_infer(infer_ty) => infer_ty.to_str(),
460       ty_err => ~"[type error]",
461       ty_param(param_ty {idx: id, def_id: did}) => {
462           let ident = match cx.ty_param_defs.borrow().find(&did.node) {
463               Some(def) => token::get_ident(def.ident).get().to_str(),
464               // This should not happen...
465               None => format!("BUG[{:?}]", id)
466           };
467           if !cx.sess.verbose() {
468               ident
469           } else {
470             format!("{}:{:?}", ident, did)
471           }
472       }
473       ty_self(..) => ~"Self",
474       ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
475         let base = ty::item_path_str(cx, did);
476         parameterized(cx,
477                       base,
478                       &substs.regions,
479                       substs.tps.as_slice(),
480                       did,
481                       false)
482       }
483       ty_trait(~ty::TyTrait {
484           def_id: did, ref substs, store: s, mutability: mutbl, ref bounds
485       }) => {
486         let base = ty::item_path_str(cx, did);
487         let ty = parameterized(cx, base, &substs.regions,
488                                substs.tps.as_slice(), did, true);
489         let bound_sep = if bounds.is_empty() { "" } else { ":" };
490         let bound_str = bounds.repr(cx);
491         format!("{}{}{}{}{}", trait_store_to_str(cx, s), mutability_to_str(mutbl), ty,
492                            bound_sep, bound_str)
493       }
494       ty_vec(ref mt, vs) => {
495         vstore_ty_to_str(cx, mt, vs)
496       }
497       ty_str(vs) => format!("{}{}", vstore_to_str(cx, vs), "str")
498     }
499 }
500
501 pub fn parameterized(cx: &ctxt,
502                      base: &str,
503                      regions: &ty::RegionSubsts,
504                      tps: &[ty::t],
505                      did: ast::DefId,
506                      is_trait: bool) -> ~str {
507
508     let mut strs = Vec::new();
509     match *regions {
510         ty::ErasedRegions => { }
511         ty::NonerasedRegions(ref regions) => {
512             for &r in regions.iter() {
513                 strs.push(region_to_str(cx, "", false, r))
514             }
515         }
516     }
517
518     let generics = if is_trait {
519         ty::lookup_trait_def(cx, did).generics.clone()
520     } else {
521         ty::lookup_item_type(cx, did).generics
522     };
523     let ty_params = generics.type_param_defs();
524     let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
525     let num_defaults = if has_defaults {
526         // We should have a borrowed version of substs instead of cloning.
527         let mut substs = ty::substs {
528             tps: Vec::from_slice(tps),
529             regions: regions.clone(),
530             self_ty: None
531         };
532         ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
533             substs.tps.pop();
534             match def.default {
535                 Some(default) => ty::subst(cx, &substs, default) == actual,
536                 None => false
537             }
538         }).len()
539     } else {
540         0
541     };
542
543     for t in tps.slice_to(tps.len() - num_defaults).iter() {
544         strs.push(ty_to_str(cx, *t))
545     }
546
547     if strs.len() > 0u {
548         format!("{}<{}>", base, strs.connect(","))
549     } else {
550         format!("{}", base)
551     }
552 }
553
554 pub fn ty_to_short_str(cx: &ctxt, typ: t) -> ~str {
555     let mut s = encoder::encoded_ty(cx, typ);
556     if s.len() >= 32u { s = s.slice(0u, 32u).to_owned(); }
557     return s;
558 }
559
560 impl<T:Repr> Repr for Option<T> {
561     fn repr(&self, tcx: &ctxt) -> ~str {
562         match self {
563             &None => ~"None",
564             &Some(ref t) => t.repr(tcx),
565         }
566     }
567 }
568
569 impl<T:Repr,U:Repr> Repr for Result<T,U> {
570     fn repr(&self, tcx: &ctxt) -> ~str {
571         match self {
572             &Ok(ref t) => t.repr(tcx),
573             &Err(ref u) => format!("Err({})", u.repr(tcx))
574         }
575     }
576 }
577
578 impl Repr for () {
579     fn repr(&self, _tcx: &ctxt) -> ~str {
580         ~"()"
581     }
582 }
583
584 impl<T:Repr> Repr for @T {
585     fn repr(&self, tcx: &ctxt) -> ~str {
586         (&**self).repr(tcx)
587     }
588 }
589
590 impl<T:Repr> Repr for ~T {
591     fn repr(&self, tcx: &ctxt) -> ~str {
592         (&**self).repr(tcx)
593     }
594 }
595
596 fn repr_vec<T:Repr>(tcx: &ctxt, v: &[T]) -> ~str {
597     vec_map_to_str(v, |t| t.repr(tcx))
598 }
599
600 impl<'a, T:Repr> Repr for &'a [T] {
601     fn repr(&self, tcx: &ctxt) -> ~str {
602         repr_vec(tcx, *self)
603     }
604 }
605
606 impl<T:Repr> Repr for OwnedSlice<T> {
607     fn repr(&self, tcx: &ctxt) -> ~str {
608         repr_vec(tcx, self.as_slice())
609     }
610 }
611
612 // This is necessary to handle types like Option<~[T]>, for which
613 // autoderef cannot convert the &[T] handler
614 impl<T:Repr> Repr for Vec<T> {
615     fn repr(&self, tcx: &ctxt) -> ~str {
616         repr_vec(tcx, self.as_slice())
617     }
618 }
619
620 impl Repr for ty::TypeParameterDef {
621     fn repr(&self, tcx: &ctxt) -> ~str {
622         format!("TypeParameterDef({:?}, {})",
623                 self.def_id,
624                 self.bounds.repr(tcx))
625     }
626 }
627
628 impl Repr for ty::RegionParameterDef {
629     fn repr(&self, _tcx: &ctxt) -> ~str {
630         format!("RegionParameterDef({}, {:?})",
631                 token::get_name(self.name),
632                 self.def_id)
633     }
634 }
635
636 impl Repr for ty::t {
637     fn repr(&self, tcx: &ctxt) -> ~str {
638         ty_to_str(tcx, *self)
639     }
640 }
641
642 impl Repr for ty::substs {
643     fn repr(&self, tcx: &ctxt) -> ~str {
644         format!("substs(regions={}, self_ty={}, tps={})",
645              self.regions.repr(tcx),
646              self.self_ty.repr(tcx),
647              self.tps.repr(tcx))
648     }
649 }
650
651 impl Repr for ty::RegionSubsts {
652     fn repr(&self, tcx: &ctxt) -> ~str {
653         match *self {
654             ty::ErasedRegions => ~"erased",
655             ty::NonerasedRegions(ref regions) => regions.repr(tcx)
656         }
657     }
658 }
659
660 impl Repr for ty::ParamBounds {
661     fn repr(&self, tcx: &ctxt) -> ~str {
662         let mut res = Vec::new();
663         for b in self.builtin_bounds.iter() {
664             res.push(match b {
665                 ty::BoundStatic => ~"'static",
666                 ty::BoundSend => ~"Send",
667                 ty::BoundSized => ~"Sized",
668                 ty::BoundPod => ~"Pod",
669                 ty::BoundShare => ~"Share",
670             });
671         }
672         for t in self.trait_bounds.iter() {
673             res.push(t.repr(tcx));
674         }
675         res.connect("+")
676     }
677 }
678
679 impl Repr for ty::TraitRef {
680     fn repr(&self, tcx: &ctxt) -> ~str {
681         trait_ref_to_str(tcx, self)
682     }
683 }
684
685 impl Repr for ast::Expr {
686     fn repr(&self, _tcx: &ctxt) -> ~str {
687         format!("expr({}: {})", self.id, pprust::expr_to_str(self))
688     }
689 }
690
691 impl Repr for ast::Item {
692     fn repr(&self, tcx: &ctxt) -> ~str {
693         format!("item({})", tcx.map.node_to_str(self.id))
694     }
695 }
696
697 impl Repr for ast::Stmt {
698     fn repr(&self, _tcx: &ctxt) -> ~str {
699         format!("stmt({}: {})",
700                 ast_util::stmt_id(self),
701                 pprust::stmt_to_str(self))
702     }
703 }
704
705 impl Repr for ast::Pat {
706     fn repr(&self, _tcx: &ctxt) -> ~str {
707         format!("pat({}: {})",
708              self.id,
709              pprust::pat_to_str(self))
710     }
711 }
712
713 impl Repr for ty::BoundRegion {
714     fn repr(&self, tcx: &ctxt) -> ~str {
715         match *self {
716             ty::BrAnon(id) => format!("BrAnon({})", id),
717             ty::BrNamed(id, name) => format!("BrNamed({}, {})",
718                                              id.repr(tcx),
719                                              token::get_name(name)),
720             ty::BrFresh(id) => format!("BrFresh({})", id),
721         }
722     }
723 }
724
725 impl Repr for ty::Region {
726     fn repr(&self, tcx: &ctxt) -> ~str {
727         match *self {
728             ty::ReEarlyBound(id, index, name) => {
729                 format!("ReEarlyBound({}, {}, {})",
730                         id, index, token::get_name(name))
731             }
732
733             ty::ReLateBound(binder_id, ref bound_region) => {
734                 format!("ReLateBound({}, {})",
735                         binder_id, bound_region.repr(tcx))
736             }
737
738             ty::ReFree(ref fr) => {
739                 format!("ReFree({}, {})",
740                         fr.scope_id,
741                         fr.bound_region.repr(tcx))
742             }
743
744             ty::ReScope(id) => {
745                 format!("ReScope({})", id)
746             }
747
748             ty::ReStatic => {
749                 format!("ReStatic")
750             }
751
752             ty::ReInfer(ReVar(ref vid)) => {
753                 format!("ReInfer({})", vid.id)
754             }
755
756             ty::ReInfer(ReSkolemized(id, ref bound_region)) => {
757                 format!("re_skolemized({}, {})",
758                         id, bound_region.repr(tcx))
759             }
760
761             ty::ReEmpty => {
762                 format!("ReEmpty")
763             }
764         }
765     }
766 }
767
768 impl Repr for ast::DefId {
769     fn repr(&self, tcx: &ctxt) -> ~str {
770         // Unfortunately, there seems to be no way to attempt to print
771         // a path for a def-id, so I'll just make a best effort for now
772         // and otherwise fallback to just printing the crate/node pair
773         if self.krate == ast::LOCAL_CRATE {
774             {
775                 match tcx.map.find(self.node) {
776                     Some(ast_map::NodeItem(..)) |
777                     Some(ast_map::NodeForeignItem(..)) |
778                     Some(ast_map::NodeMethod(..)) |
779                     Some(ast_map::NodeTraitMethod(..)) |
780                     Some(ast_map::NodeVariant(..)) |
781                     Some(ast_map::NodeStructCtor(..)) => {
782                         return format!("{:?}:{}",
783                                        *self,
784                                        ty::item_path_str(tcx, *self));
785                     }
786                     _ => {}
787                 }
788             }
789         }
790         return format!("{:?}", *self);
791     }
792 }
793
794 impl Repr for ty::ty_param_bounds_and_ty {
795     fn repr(&self, tcx: &ctxt) -> ~str {
796         format!("ty_param_bounds_and_ty \\{generics: {}, ty: {}\\}",
797              self.generics.repr(tcx),
798              self.ty.repr(tcx))
799     }
800 }
801
802 impl Repr for ty::Generics {
803     fn repr(&self, tcx: &ctxt) -> ~str {
804         format!("Generics(type_param_defs: {}, region_param_defs: {})",
805                 self.type_param_defs().repr(tcx),
806                 self.region_param_defs().repr(tcx))
807     }
808 }
809
810 impl Repr for ty::ItemVariances {
811     fn repr(&self, tcx: &ctxt) -> ~str {
812         format!("IterVariances(self_param={}, type_params={}, region_params={})",
813                 self.self_param.repr(tcx),
814                 self.type_params.repr(tcx),
815                 self.region_params.repr(tcx))
816     }
817 }
818
819 impl Repr for ty::Variance {
820     fn repr(&self, _: &ctxt) -> ~str {
821         self.to_str().to_owned()
822     }
823 }
824
825 impl Repr for ty::Method {
826     fn repr(&self, tcx: &ctxt) -> ~str {
827         format!("method(ident: {}, generics: {}, fty: {}, \
828                 explicit_self: {}, vis: {}, def_id: {})",
829                 self.ident.repr(tcx),
830                 self.generics.repr(tcx),
831                 self.fty.repr(tcx),
832                 self.explicit_self.repr(tcx),
833                 self.vis.repr(tcx),
834                 self.def_id.repr(tcx))
835     }
836 }
837
838 impl Repr for ast::Name {
839     fn repr(&self, _tcx: &ctxt) -> ~str {
840         token::get_name(*self).get().to_str()
841     }
842 }
843
844 impl Repr for ast::Ident {
845     fn repr(&self, _tcx: &ctxt) -> ~str {
846         token::get_ident(*self).get().to_str()
847     }
848 }
849
850 impl Repr for ast::ExplicitSelf_ {
851     fn repr(&self, _tcx: &ctxt) -> ~str {
852         format!("{:?}", *self)
853     }
854 }
855
856 impl Repr for ast::Visibility {
857     fn repr(&self, _tcx: &ctxt) -> ~str {
858         format!("{:?}", *self)
859     }
860 }
861
862 impl Repr for ty::BareFnTy {
863     fn repr(&self, tcx: &ctxt) -> ~str {
864         format!("BareFnTy \\{purity: {:?}, abis: {}, sig: {}\\}",
865              self.purity,
866              self.abis.to_str(),
867              self.sig.repr(tcx))
868     }
869 }
870
871 impl Repr for ty::FnSig {
872     fn repr(&self, tcx: &ctxt) -> ~str {
873         fn_sig_to_str(tcx, self)
874     }
875 }
876
877 impl Repr for typeck::MethodCallee {
878     fn repr(&self, tcx: &ctxt) -> ~str {
879         format!("MethodCallee \\{origin: {}, ty: {}, {}\\}",
880             self.origin.repr(tcx),
881             self.ty.repr(tcx),
882             self.substs.repr(tcx))
883     }
884 }
885
886 impl Repr for typeck::MethodOrigin {
887     fn repr(&self, tcx: &ctxt) -> ~str {
888         match self {
889             &typeck::MethodStatic(def_id) => {
890                 format!("MethodStatic({})", def_id.repr(tcx))
891             }
892             &typeck::MethodParam(ref p) => {
893                 p.repr(tcx)
894             }
895             &typeck::MethodObject(ref p) => {
896                 p.repr(tcx)
897             }
898         }
899     }
900 }
901
902 impl Repr for typeck::MethodParam {
903     fn repr(&self, tcx: &ctxt) -> ~str {
904         format!("MethodParam({},{:?},{:?},{:?})",
905              self.trait_id.repr(tcx),
906              self.method_num,
907              self.param_num,
908              self.bound_num)
909     }
910 }
911
912 impl Repr for typeck::MethodObject {
913     fn repr(&self, tcx: &ctxt) -> ~str {
914         format!("MethodObject({},{:?},{:?})",
915              self.trait_id.repr(tcx),
916              self.method_num,
917              self.real_index)
918     }
919 }
920
921
922 impl Repr for ty::RegionVid {
923     fn repr(&self, _tcx: &ctxt) -> ~str {
924         format!("{:?}", *self)
925     }
926 }
927
928 impl Repr for ty::TraitStore {
929     fn repr(&self, tcx: &ctxt) -> ~str {
930         match self {
931             &ty::UniqTraitStore => ~"~Trait",
932             &ty::RegionTraitStore(r) => format!("&{} Trait", r.repr(tcx))
933         }
934     }
935 }
936
937 impl Repr for ty::vstore {
938     fn repr(&self, tcx: &ctxt) -> ~str {
939         vstore_to_str(tcx, *self)
940     }
941 }
942
943 impl Repr for ty::BuiltinBound {
944     fn repr(&self, _tcx: &ctxt) -> ~str {
945         format!("{:?}", *self)
946     }
947 }
948
949 impl UserString for ty::BuiltinBound {
950     fn user_string(&self, _tcx: &ctxt) -> ~str {
951         match *self {
952             ty::BoundStatic => ~"'static",
953             ty::BoundSend => ~"Send",
954             ty::BoundSized => ~"Sized",
955             ty::BoundPod => ~"Pod",
956             ty::BoundShare => ~"Share",
957         }
958     }
959 }
960
961 impl Repr for ty::BuiltinBounds {
962     fn repr(&self, tcx: &ctxt) -> ~str {
963         self.user_string(tcx)
964     }
965 }
966
967 impl Repr for Span {
968     fn repr(&self, tcx: &ctxt) -> ~str {
969         tcx.sess.codemap().span_to_str(*self)
970     }
971 }
972
973 impl<A:UserString> UserString for @A {
974     fn user_string(&self, tcx: &ctxt) -> ~str {
975         let this: &A = &**self;
976         this.user_string(tcx)
977     }
978 }
979
980 impl UserString for ty::BuiltinBounds {
981     fn user_string(&self, tcx: &ctxt) -> ~str {
982         if self.is_empty() { ~"<no-bounds>" } else {
983             let mut result = Vec::new();
984             for bb in self.iter() {
985                 result.push(bb.user_string(tcx));
986             }
987             result.connect("+")
988         }
989     }
990 }
991
992 impl UserString for ty::TraitRef {
993     fn user_string(&self, tcx: &ctxt) -> ~str {
994         let base = ty::item_path_str(tcx, self.def_id);
995         if tcx.sess.verbose() && self.substs.self_ty.is_some() {
996             let mut all_tps = self.substs.tps.clone();
997             for &t in self.substs.self_ty.iter() { all_tps.push(t); }
998             parameterized(tcx, base, &self.substs.regions,
999                           all_tps.as_slice(), self.def_id, true)
1000         } else {
1001             parameterized(tcx, base, &self.substs.regions,
1002                           self.substs.tps.as_slice(), self.def_id, true)
1003         }
1004     }
1005 }
1006
1007 impl UserString for ty::t {
1008     fn user_string(&self, tcx: &ctxt) -> ~str {
1009         ty_to_str(tcx, *self)
1010     }
1011 }
1012
1013 impl UserString for ast::Ident {
1014     fn user_string(&self, _tcx: &ctxt) -> ~str {
1015         token::get_name(self.name).get().to_owned()
1016     }
1017 }
1018
1019 impl Repr for AbiSet {
1020     fn repr(&self, _tcx: &ctxt) -> ~str {
1021         self.to_str()
1022     }
1023 }
1024
1025 impl UserString for AbiSet {
1026     fn user_string(&self, _tcx: &ctxt) -> ~str {
1027         self.to_str()
1028     }
1029 }
1030
1031 impl Repr for ty::UpvarId {
1032     fn repr(&self, tcx: &ctxt) -> ~str {
1033         format!("UpvarId({};`{}`;{})",
1034              self.var_id,
1035              ty::local_var_name_str(tcx, self.var_id),
1036              self.closure_expr_id)
1037     }
1038 }
1039
1040 impl Repr for ast::Mutability {
1041     fn repr(&self, _tcx: &ctxt) -> ~str {
1042         format!("{:?}", *self)
1043     }
1044 }
1045
1046 impl Repr for ty::BorrowKind {
1047     fn repr(&self, _tcx: &ctxt) -> ~str {
1048         format!("{:?}", *self)
1049     }
1050 }
1051
1052 impl Repr for ty::UpvarBorrow {
1053     fn repr(&self, tcx: &ctxt) -> ~str {
1054         format!("UpvarBorrow({}, {})",
1055              self.kind.repr(tcx),
1056              self.region.repr(tcx))
1057     }
1058 }