]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
/*! -> //!
[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 middle::def;
13 use middle::subst::{VecPerParamSpace,Subst};
14 use middle::subst;
15 use middle::ty::{BoundRegion, BrAnon, BrNamed};
16 use middle::ty::{ReEarlyBound, BrFresh, ctxt};
17 use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
18 use middle::ty::{ReSkolemized, ReVar, BrEnv};
19 use middle::ty::{mt, Ty, ParamTy};
20 use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
21 use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
22 use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
23 use middle::ty::{ty_unboxed_closure};
24 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
25 use middle::ty;
26 use middle::typeck;
27 use middle::typeck::check::regionmanip;
28
29 use std::rc::Rc;
30 use syntax::abi;
31 use syntax::ast_map;
32 use syntax::codemap::{Span, Pos};
33 use syntax::parse::token;
34 use syntax::print::pprust;
35 use syntax::ptr::P;
36 use syntax::{ast, ast_util};
37 use syntax::owned_slice::OwnedSlice;
38
39 /// Produces a string suitable for debugging output.
40 pub trait Repr<'tcx> for Sized? {
41     fn repr(&self, tcx: &ctxt<'tcx>) -> String;
42 }
43
44 /// Produces a string suitable for showing to the user.
45 pub trait UserString<'tcx> {
46     fn user_string(&self, tcx: &ctxt<'tcx>) -> String;
47 }
48
49 pub fn note_and_explain_region(cx: &ctxt,
50                                prefix: &str,
51                                region: ty::Region,
52                                suffix: &str) -> Option<Span> {
53     match explain_region_and_span(cx, region) {
54       (ref str, Some(span)) => {
55         cx.sess.span_note(
56             span,
57             format!("{}{}{}", prefix, *str, suffix).as_slice());
58         Some(span)
59       }
60       (ref str, None) => {
61         cx.sess.note(
62             format!("{}{}{}", prefix, *str, suffix).as_slice());
63         None
64       }
65     }
66 }
67
68 /// When a free region is associated with `item`, how should we describe the item in the error
69 /// message.
70 fn item_scope_tag(item: &ast::Item) -> &'static str {
71     match item.node {
72         ast::ItemImpl(..) => "impl",
73         ast::ItemStruct(..) => "struct",
74         ast::ItemEnum(..) => "enum",
75         ast::ItemTrait(..) => "trait",
76         ast::ItemFn(..) => "function body",
77         _ => "item"
78     }
79 }
80
81 pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
82                             -> (String, Option<Span>) {
83     return match region {
84       ReScope(scope) => {
85         match cx.map.find(scope.node_id()) {
86           Some(ast_map::NodeBlock(ref blk)) => {
87             explain_span(cx, "block", blk.span)
88           }
89           Some(ast_map::NodeExpr(expr)) => {
90             match expr.node {
91               ast::ExprCall(..) => explain_span(cx, "call", expr.span),
92               ast::ExprMethodCall(..) => {
93                 explain_span(cx, "method call", expr.span)
94               },
95               ast::ExprMatch(_, _, ast::MatchIfLetDesugar) => explain_span(cx, "if let", expr.span),
96               ast::ExprMatch(_, _, ast::MatchWhileLetDesugar) => {
97                   explain_span(cx, "while let", expr.span)
98               },
99               ast::ExprMatch(..) => explain_span(cx, "match", expr.span),
100               _ => explain_span(cx, "expression", expr.span)
101             }
102           }
103           Some(ast_map::NodeStmt(stmt)) => {
104               explain_span(cx, "statement", stmt.span)
105           }
106           Some(ast_map::NodeItem(it)) => {
107               let tag = item_scope_tag(&*it);
108               explain_span(cx, tag, it.span)
109           }
110           Some(_) | None => {
111             // this really should not happen
112             (format!("unknown scope: {}.  Please report a bug.", scope), None)
113           }
114         }
115       }
116
117       ReFree(ref fr) => {
118         let prefix = match fr.bound_region {
119           BrAnon(idx) => {
120               format!("the anonymous lifetime #{} defined on", idx + 1)
121           }
122           BrFresh(_) => "an anonymous lifetime defined on".to_string(),
123           _ => {
124               format!("the lifetime {} as defined on",
125                       bound_region_ptr_to_string(cx, fr.bound_region))
126           }
127         };
128
129         match cx.map.find(fr.scope.node_id()) {
130           Some(ast_map::NodeBlock(ref blk)) => {
131               let (msg, opt_span) = explain_span(cx, "block", blk.span);
132               (format!("{} {}", prefix, msg), opt_span)
133           }
134           Some(ast_map::NodeItem(it)) => {
135               let tag = item_scope_tag(&*it);
136               let (msg, opt_span) = explain_span(cx, tag, it.span);
137               (format!("{} {}", prefix, msg), opt_span)
138           }
139           Some(_) | None => {
140               // this really should not happen
141               (format!("{} unknown free region bounded by scope {}", prefix, fr.scope), None)
142           }
143         }
144       }
145
146       ReStatic => { ("the static lifetime".to_string(), None) }
147
148       ReEmpty => { ("the empty lifetime".to_string(), None) }
149
150       ReEarlyBound(_, _, _, name) => {
151         (format!("{}", token::get_name(name)), None)
152       }
153
154       // I believe these cases should not occur (except when debugging,
155       // perhaps)
156       ty::ReInfer(_) | ty::ReLateBound(..) => {
157         (format!("lifetime {}", region), None)
158       }
159     };
160
161     fn explain_span(cx: &ctxt, heading: &str, span: Span)
162                     -> (String, Option<Span>) {
163         let lo = cx.sess.codemap().lookup_char_pos_adj(span.lo);
164         (format!("the {} at {}:{}", heading, lo.line, lo.col.to_uint()),
165          Some(span))
166     }
167 }
168
169 pub fn bound_region_ptr_to_string(cx: &ctxt, br: BoundRegion) -> String {
170     bound_region_to_string(cx, "", false, br)
171 }
172
173 pub fn bound_region_to_string(cx: &ctxt,
174                            prefix: &str, space: bool,
175                            br: BoundRegion) -> String {
176     let space_str = if space { " " } else { "" };
177
178     if cx.sess.verbose() {
179         return format!("{}{}{}", prefix, br.repr(cx), space_str)
180     }
181
182     match br {
183         BrNamed(_, name) => {
184             format!("{}{}{}", prefix, token::get_name(name), space_str)
185         }
186         BrAnon(_) | BrFresh(_) | BrEnv => prefix.to_string()
187     }
188 }
189
190 // In general, if you are giving a region error message,
191 // you should use `explain_region()` or, better yet,
192 // `note_and_explain_region()`
193 pub fn region_ptr_to_string(cx: &ctxt, region: Region) -> String {
194     region_to_string(cx, "&", true, region)
195 }
196
197 pub fn region_to_string(cx: &ctxt, prefix: &str, space: bool, region: Region) -> String {
198     let space_str = if space { " " } else { "" };
199
200     if cx.sess.verbose() {
201         return format!("{}{}{}", prefix, region.repr(cx), space_str)
202     }
203
204     // These printouts are concise.  They do not contain all the information
205     // the user might want to diagnose an error, but there is basically no way
206     // to fit that into a short string.  Hence the recommendation to use
207     // `explain_region()` or `note_and_explain_region()`.
208     match region {
209         ty::ReScope(_) => prefix.to_string(),
210         ty::ReEarlyBound(_, _, _, name) => {
211             token::get_name(name).get().to_string()
212         }
213         ty::ReLateBound(_, br) => bound_region_to_string(cx, prefix, space, br),
214         ty::ReFree(ref fr) => bound_region_to_string(cx, prefix, space, fr.bound_region),
215         ty::ReInfer(ReSkolemized(_, br)) => {
216             bound_region_to_string(cx, prefix, space, br)
217         }
218         ty::ReInfer(ReVar(_)) => prefix.to_string(),
219         ty::ReStatic => format!("{}'static{}", prefix, space_str),
220         ty::ReEmpty => format!("{}'<empty>{}", prefix, space_str),
221     }
222 }
223
224 pub fn mutability_to_string(m: ast::Mutability) -> String {
225     match m {
226         ast::MutMutable => "mut ".to_string(),
227         ast::MutImmutable => "".to_string(),
228     }
229 }
230
231 pub fn mt_to_string<'tcx>(cx: &ctxt<'tcx>, m: &mt<'tcx>) -> String {
232     format!("{}{}",
233         mutability_to_string(m.mutbl),
234         ty_to_string(cx, m.ty))
235 }
236
237 pub fn trait_store_to_string(cx: &ctxt, s: ty::TraitStore) -> String {
238     match s {
239         ty::UniqTraitStore => "Box ".to_string(),
240         ty::RegionTraitStore(r, m) => {
241             format!("{}{}", region_ptr_to_string(cx, r), mutability_to_string(m))
242         }
243     }
244 }
245
246 pub fn vec_map_to_string<T>(ts: &[T], f: |t: &T| -> String) -> String {
247     let tstrs = ts.iter().map(f).collect::<Vec<String>>();
248     format!("[{}]", tstrs.connect(", "))
249 }
250
251 pub fn fn_sig_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::FnSig<'tcx>) -> String {
252     format!("fn{} -> {}", typ.inputs.repr(cx), typ.output.repr(cx))
253 }
254
255 pub fn trait_ref_to_string<'tcx>(cx: &ctxt<'tcx>,
256                                  trait_ref: &ty::TraitRef<'tcx>) -> String {
257     trait_ref.user_string(cx).to_string()
258 }
259
260 pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
261     fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
262                                fn_style: ast::FnStyle,
263                                abi: abi::Abi,
264                                ident: Option<ast::Ident>,
265                                sig: &ty::FnSig<'tcx>)
266                                -> String {
267         let mut s = String::new();
268         match fn_style {
269             ast::NormalFn => {}
270             _ => {
271                 s.push_str(fn_style.to_string().as_slice());
272                 s.push(' ');
273             }
274         };
275
276         if abi != abi::Rust {
277             s.push_str(format!("extern {} ", abi.to_string()).as_slice());
278         };
279
280         s.push_str("fn");
281
282         match ident {
283             Some(i) => {
284                 s.push(' ');
285                 s.push_str(token::get_ident(i).get());
286             }
287             _ => { }
288         }
289
290         push_sig_to_string(cx, &mut s, '(', ')', sig, "");
291
292         s
293     }
294
295     fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String {
296         let mut s = String::new();
297
298         match cty.store {
299             ty::UniqTraitStore => {}
300             ty::RegionTraitStore(region, _) => {
301                 s.push_str(region_to_string(cx, "", true, region).as_slice());
302             }
303         }
304
305         match cty.fn_style {
306             ast::NormalFn => {}
307             _ => {
308                 s.push_str(cty.fn_style.to_string().as_slice());
309                 s.push(' ');
310             }
311         };
312
313         let bounds_str = cty.bounds.user_string(cx);
314
315         match cty.store {
316             ty::UniqTraitStore => {
317                 assert_eq!(cty.onceness, ast::Once);
318                 s.push_str("proc");
319                 push_sig_to_string(cx, &mut s, '(', ')', &cty.sig,
320                                    bounds_str.as_slice());
321             }
322             ty::RegionTraitStore(..) => {
323                 match cty.onceness {
324                     ast::Many => {}
325                     ast::Once => s.push_str("once ")
326                 }
327                 push_sig_to_string(cx, &mut s, '|', '|', &cty.sig,
328                                    bounds_str.as_slice());
329             }
330         }
331
332         s
333     }
334
335     fn push_sig_to_string<'tcx>(cx: &ctxt<'tcx>,
336                                 s: &mut String,
337                                 bra: char,
338                                 ket: char,
339                                 sig: &ty::FnSig<'tcx>,
340                                 bounds: &str) {
341         s.push(bra);
342         let strs = sig.inputs
343             .iter()
344             .map(|a| ty_to_string(cx, *a))
345             .collect::<Vec<_>>();
346         s.push_str(strs.connect(", ").as_slice());
347         if sig.variadic {
348             s.push_str(", ...");
349         }
350         s.push(ket);
351
352         if !bounds.is_empty() {
353             s.push_str(":");
354             s.push_str(bounds);
355         }
356
357         match sig.output {
358             ty::FnConverging(t) => {
359                 if !ty::type_is_nil(t) {
360                    s.push_str(" -> ");
361                    s.push_str(ty_to_string(cx, t).as_slice());
362                 }
363             }
364             ty::FnDiverging => {
365                 s.push_str(" -> !");
366             }
367         }
368     }
369
370     fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
371         let print_var_ids = cx.sess.verbose();
372         match ty {
373             ty::TyVar(ref vid) if print_var_ids => vid.repr(cx),
374             ty::IntVar(ref vid) if print_var_ids => vid.repr(cx),
375             ty::FloatVar(ref vid) if print_var_ids => vid.repr(cx),
376             ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => format!("_"),
377             ty::SkolemizedTy(v) => format!("SkolemizedTy({})", v),
378             ty::SkolemizedIntTy(v) => format!("SkolemizedIntTy({})", v)
379         }
380     }
381
382     // pretty print the structural type representation:
383     match typ.sty {
384         ty_bool => "bool".to_string(),
385         ty_char => "char".to_string(),
386         ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(),
387         ty_uint(t) => ast_util::uint_ty_to_string(t, None).to_string(),
388         ty_float(t) => ast_util::float_ty_to_string(t).to_string(),
389         ty_uniq(typ) => format!("Box<{}>", ty_to_string(cx, typ)),
390         ty_ptr(ref tm) => {
391             format!("*{} {}", match tm.mutbl {
392                 ast::MutMutable => "mut",
393                 ast::MutImmutable => "const",
394             }, ty_to_string(cx, tm.ty))
395         }
396         ty_rptr(r, ref tm) => {
397             let mut buf = region_ptr_to_string(cx, r);
398             buf.push_str(mt_to_string(cx, tm).as_slice());
399             buf
400         }
401         ty_open(typ) =>
402             format!("opened<{}>", ty_to_string(cx, typ)),
403         ty_tup(ref elems) => {
404             let strs = elems
405                 .iter()
406                 .map(|elem| ty_to_string(cx, *elem))
407                 .collect::<Vec<_>>();
408             match strs.as_slice() {
409                 [ref string] => format!("({},)", string),
410                 strs => format!("({})", strs.connect(", "))
411             }
412         }
413         ty_closure(ref f) => {
414             closure_to_string(cx, &**f)
415         }
416         ty_bare_fn(ref f) => {
417             bare_fn_to_string(cx, f.fn_style, f.abi, None, &f.sig)
418         }
419         ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
420         ty_err => "[type error]".to_string(),
421         ty_param(ref param_ty) => {
422             if cx.sess.verbose() {
423                 param_ty.repr(cx)
424             } else {
425                 param_ty.user_string(cx)
426             }
427         }
428         ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
429             let base = ty::item_path_str(cx, did);
430             let generics = ty::lookup_item_type(cx, did).generics;
431             parameterized(cx, base.as_slice(), substs, &generics)
432         }
433         ty_trait(box ty::TyTrait {
434             ref principal, ref bounds
435         }) => {
436             let base = ty::item_path_str(cx, principal.def_id);
437             let trait_def = ty::lookup_trait_def(cx, principal.def_id);
438             let ty = parameterized(cx, base.as_slice(),
439                                    &principal.substs, &trait_def.generics);
440             let bound_str = bounds.user_string(cx);
441             let bound_sep = if bound_str.is_empty() { "" } else { "+" };
442             format!("{}{}{}",
443                     ty,
444                     bound_sep,
445                     bound_str)
446         }
447         ty_str => "str".to_string(),
448         ty_unboxed_closure(ref did, _, ref substs) => {
449             let unboxed_closures = cx.unboxed_closures.borrow();
450             unboxed_closures.get(did).map(|cl| {
451                 closure_to_string(cx, &cl.closure_type.subst(cx, substs))
452             }).unwrap_or_else(|| "closure".to_string())
453         }
454         ty_vec(t, sz) => {
455             let inner_str = ty_to_string(cx, t);
456             match sz {
457                 Some(n) => format!("[{}, ..{}]", inner_str, n),
458                 None => format!("[{}]", inner_str),
459             }
460         }
461     }
462 }
463
464 pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory)
465                                      -> &'static str {
466     match *category {
467         ty::StaticExplicitSelfCategory => "static",
468         ty::ByValueExplicitSelfCategory => "self",
469         ty::ByReferenceExplicitSelfCategory(_, ast::MutMutable) => {
470             "&mut self"
471         }
472         ty::ByReferenceExplicitSelfCategory(_, ast::MutImmutable) => "&self",
473         ty::ByBoxExplicitSelfCategory => "Box<self>",
474     }
475 }
476
477 pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
478                            base: &str,
479                            substs: &subst::Substs<'tcx>,
480                            generics: &ty::Generics<'tcx>)
481                            -> String
482 {
483     if cx.sess.verbose() {
484         if substs.is_noop() {
485             return format!("{}", base);
486         } else {
487             return format!("{}<{},{}>",
488                            base,
489                            substs.regions.repr(cx),
490                            substs.types.repr(cx));
491         }
492     }
493
494     let mut strs = Vec::new();
495
496     match substs.regions {
497         subst::ErasedRegions => { }
498         subst::NonerasedRegions(ref regions) => {
499             for &r in regions.iter() {
500                 let s = region_to_string(cx, "", false, r);
501                 if s.is_empty() {
502                     // This happens when the value of the region
503                     // parameter is not easily serialized. This may be
504                     // because the user omitted it in the first place,
505                     // or because it refers to some block in the code,
506                     // etc. I'm not sure how best to serialize this.
507                     strs.push(format!("'_"));
508                 } else {
509                     strs.push(s)
510                 }
511             }
512         }
513     }
514
515     let tps = substs.types.get_slice(subst::TypeSpace);
516     let ty_params = generics.types.get_slice(subst::TypeSpace);
517     let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
518     let num_defaults = if has_defaults {
519         ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
520             match def.default {
521                 Some(default) => default.subst(cx, substs) == actual,
522                 None => false
523             }
524         }).count()
525     } else {
526         0
527     };
528
529     for t in tps[..tps.len() - num_defaults].iter() {
530         strs.push(ty_to_string(cx, *t))
531     }
532
533     if strs.len() > 0u {
534         format!("{}<{}>", base, strs.connect(", "))
535     } else {
536         format!("{}", base)
537     }
538 }
539
540 pub fn ty_to_short_str<'tcx>(cx: &ctxt<'tcx>, typ: Ty<'tcx>) -> String {
541     let mut s = typ.repr(cx).to_string();
542     if s.len() >= 32u {
543         s = s.as_slice().slice(0u, 32u).to_string();
544     }
545     return s;
546 }
547
548 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Option<T> {
549     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
550         match self {
551             &None => "None".to_string(),
552             &Some(ref t) => t.repr(tcx),
553         }
554     }
555 }
556
557 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for P<T> {
558     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
559         (*self).repr(tcx)
560     }
561 }
562
563 impl<'tcx,T:Repr<'tcx>,U:Repr<'tcx>> Repr<'tcx> for Result<T,U> {
564     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
565         match self {
566             &Ok(ref t) => t.repr(tcx),
567             &Err(ref u) => format!("Err({})", u.repr(tcx))
568         }
569     }
570 }
571
572 impl<'tcx> Repr<'tcx> for () {
573     fn repr(&self, _tcx: &ctxt) -> String {
574         "()".to_string()
575     }
576 }
577
578 impl<'a, 'tcx, Sized? T:Repr<'tcx>> Repr<'tcx> for &'a T {
579     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
580         Repr::repr(*self, tcx)
581     }
582 }
583
584 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Rc<T> {
585     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
586         (&**self).repr(tcx)
587     }
588 }
589
590 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Box<T> {
591     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
592         (&**self).repr(tcx)
593     }
594 }
595
596 fn repr_vec<'tcx, T:Repr<'tcx>>(tcx: &ctxt<'tcx>, v: &[T]) -> String {
597     vec_map_to_string(v, |t| t.repr(tcx))
598 }
599
600 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for [T] {
601     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
602         repr_vec(tcx, self)
603     }
604 }
605
606 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice<T> {
607     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
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<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec<T> {
615     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
616         repr_vec(tcx, self.as_slice())
617     }
618 }
619
620 impl<'tcx, T:UserString<'tcx>> UserString<'tcx> for Vec<T> {
621     fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
622         let strs: Vec<String> =
623             self.iter().map(|t| t.user_string(tcx)).collect();
624         strs.connect(", ")
625     }
626 }
627
628 impl<'tcx> Repr<'tcx> for def::Def {
629     fn repr(&self, _tcx: &ctxt) -> String {
630         format!("{}", *self)
631     }
632 }
633
634 impl<'tcx> Repr<'tcx> for ty::TypeParameterDef<'tcx> {
635     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
636         format!("TypeParameterDef({}, {}, {}/{})",
637                 self.def_id,
638                 self.bounds.repr(tcx),
639                 self.space,
640                 self.index)
641     }
642 }
643
644 impl<'tcx> Repr<'tcx> for ty::RegionParameterDef {
645     fn repr(&self, tcx: &ctxt) -> String {
646         format!("RegionParameterDef(name={}, def_id={}, bounds={})",
647                 token::get_name(self.name),
648                 self.def_id.repr(tcx),
649                 self.bounds.repr(tcx))
650     }
651 }
652
653 impl<'tcx> Repr<'tcx> for ty::TyS<'tcx> {
654     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
655         ty_to_string(tcx, self)
656     }
657 }
658
659 impl<'tcx> Repr<'tcx> for ty::mt<'tcx> {
660     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
661         mt_to_string(tcx, self)
662     }
663 }
664
665 impl<'tcx> Repr<'tcx> for subst::Substs<'tcx> {
666     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
667         format!("Substs[types={}, regions={}]",
668                        self.types.repr(tcx),
669                        self.regions.repr(tcx))
670     }
671 }
672
673 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for subst::VecPerParamSpace<T> {
674     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
675         format!("[{};{};{};{}]",
676                 self.get_slice(subst::TypeSpace).repr(tcx),
677                 self.get_slice(subst::SelfSpace).repr(tcx),
678                 self.get_slice(subst::AssocSpace).repr(tcx),
679                 self.get_slice(subst::FnSpace).repr(tcx))
680     }
681 }
682
683 impl<'tcx> Repr<'tcx> for ty::ItemSubsts<'tcx> {
684     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
685         format!("ItemSubsts({})", self.substs.repr(tcx))
686     }
687 }
688
689 impl<'tcx> Repr<'tcx> for subst::RegionSubsts {
690     fn repr(&self, tcx: &ctxt) -> String {
691         match *self {
692             subst::ErasedRegions => "erased".to_string(),
693             subst::NonerasedRegions(ref regions) => regions.repr(tcx)
694         }
695     }
696 }
697
698 impl<'tcx> Repr<'tcx> for ty::BuiltinBounds {
699     fn repr(&self, _tcx: &ctxt) -> String {
700         let mut res = Vec::new();
701         for b in self.iter() {
702             res.push(match b {
703                 ty::BoundSend => "Send".to_string(),
704                 ty::BoundSized => "Sized".to_string(),
705                 ty::BoundCopy => "Copy".to_string(),
706                 ty::BoundSync => "Sync".to_string(),
707             });
708         }
709         res.connect("+")
710     }
711 }
712
713 impl<'tcx> Repr<'tcx> for ty::ExistentialBounds {
714     fn repr(&self, tcx: &ctxt) -> String {
715         self.user_string(tcx)
716     }
717 }
718
719 impl<'tcx> Repr<'tcx> for ty::ParamBounds<'tcx> {
720     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
721         let mut res = Vec::new();
722         res.push(self.builtin_bounds.repr(tcx));
723         for t in self.trait_bounds.iter() {
724             res.push(t.repr(tcx));
725         }
726         res.connect("+")
727     }
728 }
729
730 impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
731     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
732         // when printing out the debug representation, we don't need
733         // to enumerate the `for<...>` etc because the debruijn index
734         // tells you everything you need to know.
735         let base = ty::item_path_str(tcx, self.def_id);
736         let trait_def = ty::lookup_trait_def(tcx, self.def_id);
737         format!("<{} : {}>",
738                 self.substs.self_ty().repr(tcx),
739                 parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics))
740     }
741 }
742
743 impl<'tcx> Repr<'tcx> for ty::TraitDef<'tcx> {
744     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
745         format!("TraitDef(generics={}, bounds={}, trait_ref={})",
746                 self.generics.repr(tcx),
747                 self.bounds.repr(tcx),
748                 self.trait_ref.repr(tcx))
749     }
750 }
751
752 impl<'tcx> Repr<'tcx> for ast::TraitItem {
753     fn repr(&self, _tcx: &ctxt) -> String {
754         match *self {
755             ast::RequiredMethod(ref data) => format!("RequiredMethod({}, id={})",
756                                                      data.ident, data.id),
757             ast::ProvidedMethod(ref data) => format!("ProvidedMethod(id={})",
758                                                      data.id),
759             ast::TypeTraitItem(ref data) => format!("TypeTraitItem({}, id={})",
760                                                      data.ty_param.ident, data.ty_param.id),
761         }
762     }
763 }
764
765 impl<'tcx> Repr<'tcx> for ast::Expr {
766     fn repr(&self, _tcx: &ctxt) -> String {
767         format!("expr({}: {})", self.id, pprust::expr_to_string(self))
768     }
769 }
770
771 impl<'tcx> Repr<'tcx> for ast::Path {
772     fn repr(&self, _tcx: &ctxt) -> String {
773         format!("path({})", pprust::path_to_string(self))
774     }
775 }
776
777 impl<'tcx> UserString<'tcx> for ast::Path {
778     fn user_string(&self, _tcx: &ctxt) -> String {
779         pprust::path_to_string(self)
780     }
781 }
782
783 impl<'tcx> Repr<'tcx> for ast::Ty {
784     fn repr(&self, _tcx: &ctxt) -> String {
785         format!("type({})", pprust::ty_to_string(self))
786     }
787 }
788
789 impl<'tcx> Repr<'tcx> for ast::Item {
790     fn repr(&self, tcx: &ctxt) -> String {
791         format!("item({})", tcx.map.node_to_string(self.id))
792     }
793 }
794
795 impl<'tcx> Repr<'tcx> for ast::Lifetime {
796     fn repr(&self, _tcx: &ctxt) -> String {
797         format!("lifetime({}: {})", self.id, pprust::lifetime_to_string(self))
798     }
799 }
800
801 impl<'tcx> Repr<'tcx> for ast::Stmt {
802     fn repr(&self, _tcx: &ctxt) -> String {
803         format!("stmt({}: {})",
804                 ast_util::stmt_id(self),
805                 pprust::stmt_to_string(self))
806     }
807 }
808
809 impl<'tcx> Repr<'tcx> for ast::Pat {
810     fn repr(&self, _tcx: &ctxt) -> String {
811         format!("pat({}: {})", self.id, pprust::pat_to_string(self))
812     }
813 }
814
815 impl<'tcx> Repr<'tcx> for ty::BoundRegion {
816     fn repr(&self, tcx: &ctxt) -> String {
817         match *self {
818             ty::BrAnon(id) => format!("BrAnon({})", id),
819             ty::BrNamed(id, name) => {
820                 format!("BrNamed({}, {})", id.repr(tcx), token::get_name(name))
821             }
822             ty::BrFresh(id) => format!("BrFresh({})", id),
823             ty::BrEnv => "BrEnv".to_string()
824         }
825     }
826 }
827
828 impl<'tcx> Repr<'tcx> for ty::Region {
829     fn repr(&self, tcx: &ctxt) -> String {
830         match *self {
831             ty::ReEarlyBound(id, space, index, name) => {
832                 format!("ReEarlyBound({}, {}, {}, {})",
833                                id,
834                                space,
835                                index,
836                                token::get_name(name))
837             }
838
839             ty::ReLateBound(binder_id, ref bound_region) => {
840                 format!("ReLateBound({}, {})",
841                         binder_id,
842                         bound_region.repr(tcx))
843             }
844
845             ty::ReFree(ref fr) => fr.repr(tcx),
846
847             ty::ReScope(id) => {
848                 format!("ReScope({})", id)
849             }
850
851             ty::ReStatic => {
852                 "ReStatic".to_string()
853             }
854
855             ty::ReInfer(ReVar(ref vid)) => {
856                 format!("{}", vid)
857             }
858
859             ty::ReInfer(ReSkolemized(id, ref bound_region)) => {
860                 format!("re_skolemized({}, {})", id, bound_region.repr(tcx))
861             }
862
863             ty::ReEmpty => {
864                 "ReEmpty".to_string()
865             }
866         }
867     }
868 }
869
870 impl<'tcx> UserString<'tcx> for ty::Region {
871     fn user_string(&self, tcx: &ctxt) -> String {
872         region_to_string(tcx, "", false, *self)
873     }
874 }
875
876 impl<'tcx> Repr<'tcx> for ty::FreeRegion {
877     fn repr(&self, tcx: &ctxt) -> String {
878         format!("ReFree({}, {})",
879                 self.scope.node_id(),
880                 self.bound_region.repr(tcx))
881     }
882 }
883
884 impl<'tcx> Repr<'tcx> for ast::DefId {
885     fn repr(&self, tcx: &ctxt) -> String {
886         // Unfortunately, there seems to be no way to attempt to print
887         // a path for a def-id, so I'll just make a best effort for now
888         // and otherwise fallback to just printing the crate/node pair
889         if self.krate == ast::LOCAL_CRATE {
890             match tcx.map.find(self.node) {
891                 Some(ast_map::NodeItem(..)) |
892                 Some(ast_map::NodeForeignItem(..)) |
893                 Some(ast_map::NodeImplItem(..)) |
894                 Some(ast_map::NodeTraitItem(..)) |
895                 Some(ast_map::NodeVariant(..)) |
896                 Some(ast_map::NodeStructCtor(..)) => {
897                     return format!(
898                                 "{}:{}",
899                                 *self,
900                                 ty::item_path_str(tcx, *self))
901                 }
902                 _ => {}
903             }
904         }
905         return format!("{}", *self)
906     }
907 }
908
909 impl<'tcx> Repr<'tcx> for ty::Polytype<'tcx> {
910     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
911         format!("Polytype {{generics: {}, ty: {}}}",
912                 self.generics.repr(tcx),
913                 self.ty.repr(tcx))
914     }
915 }
916
917 impl<'tcx> Repr<'tcx> for ty::Generics<'tcx> {
918     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
919         format!("Generics(types: {}, regions: {})",
920                 self.types.repr(tcx),
921                 self.regions.repr(tcx))
922     }
923 }
924
925 impl<'tcx> Repr<'tcx> for ty::GenericBounds<'tcx> {
926     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
927         format!("GenericBounds(types: {}, regions: {})",
928                 self.types.repr(tcx),
929                 self.regions.repr(tcx))
930     }
931 }
932
933 impl<'tcx> Repr<'tcx> for ty::ItemVariances {
934     fn repr(&self, tcx: &ctxt) -> String {
935         format!("ItemVariances(types={}, \
936                 regions={})",
937                 self.types.repr(tcx),
938                 self.regions.repr(tcx))
939     }
940 }
941
942 impl<'tcx> Repr<'tcx> for ty::Variance {
943     fn repr(&self, _: &ctxt) -> String {
944         // The first `.to_string()` returns a &'static str (it is not an implementation
945         // of the ToString trait). Because of that, we need to call `.to_string()` again
946         // if we want to have a `String`.
947         let result: &'static str = (*self).to_string();
948         result.to_string()
949     }
950 }
951
952 impl<'tcx> Repr<'tcx> for ty::Method<'tcx> {
953     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
954         format!("method(name: {}, generics: {}, fty: {}, \
955                  explicit_self: {}, vis: {}, def_id: {})",
956                 self.name.repr(tcx),
957                 self.generics.repr(tcx),
958                 self.fty.repr(tcx),
959                 self.explicit_self.repr(tcx),
960                 self.vis.repr(tcx),
961                 self.def_id.repr(tcx))
962     }
963 }
964
965 impl<'tcx> Repr<'tcx> for ast::Name {
966     fn repr(&self, _tcx: &ctxt) -> String {
967         token::get_name(*self).get().to_string()
968     }
969 }
970
971 impl<'tcx> UserString<'tcx> for ast::Name {
972     fn user_string(&self, _tcx: &ctxt) -> String {
973         token::get_name(*self).get().to_string()
974     }
975 }
976
977 impl<'tcx> Repr<'tcx> for ast::Ident {
978     fn repr(&self, _tcx: &ctxt) -> String {
979         token::get_ident(*self).get().to_string()
980     }
981 }
982
983 impl<'tcx> Repr<'tcx> for ast::ExplicitSelf_ {
984     fn repr(&self, _tcx: &ctxt) -> String {
985         format!("{}", *self)
986     }
987 }
988
989 impl<'tcx> Repr<'tcx> for ast::Visibility {
990     fn repr(&self, _tcx: &ctxt) -> String {
991         format!("{}", *self)
992     }
993 }
994
995 impl<'tcx> Repr<'tcx> for ty::BareFnTy<'tcx> {
996     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
997         format!("BareFnTy {{fn_style: {}, abi: {}, sig: {}}}",
998                 self.fn_style,
999                 self.abi.to_string(),
1000                 self.sig.repr(tcx))
1001     }
1002 }
1003
1004 impl<'tcx> Repr<'tcx> for ty::FnSig<'tcx> {
1005     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1006         fn_sig_to_string(tcx, self)
1007     }
1008 }
1009
1010 impl<'tcx> Repr<'tcx> for ty::FnOutput<'tcx> {
1011     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1012         match *self {
1013             ty::FnConverging(ty) =>
1014                 format!("FnConverging({0})", ty.repr(tcx)),
1015             ty::FnDiverging =>
1016                 "FnDiverging".to_string()
1017         }
1018     }
1019 }
1020
1021 impl<'tcx> Repr<'tcx> for typeck::MethodCallee<'tcx> {
1022     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1023         format!("MethodCallee {{origin: {}, ty: {}, {}}}",
1024                 self.origin.repr(tcx),
1025                 self.ty.repr(tcx),
1026                 self.substs.repr(tcx))
1027     }
1028 }
1029
1030 impl<'tcx> Repr<'tcx> for typeck::MethodOrigin<'tcx> {
1031     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1032         match self {
1033             &typeck::MethodStatic(def_id) => {
1034                 format!("MethodStatic({})", def_id.repr(tcx))
1035             }
1036             &typeck::MethodStaticUnboxedClosure(def_id) => {
1037                 format!("MethodStaticUnboxedClosure({})", def_id.repr(tcx))
1038             }
1039             &typeck::MethodTypeParam(ref p) => {
1040                 p.repr(tcx)
1041             }
1042             &typeck::MethodTraitObject(ref p) => {
1043                 p.repr(tcx)
1044             }
1045         }
1046     }
1047 }
1048
1049 impl<'tcx> Repr<'tcx> for typeck::MethodParam<'tcx> {
1050     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1051         format!("MethodParam({},{})",
1052                 self.trait_ref.repr(tcx),
1053                 self.method_num)
1054     }
1055 }
1056
1057 impl<'tcx> Repr<'tcx> for typeck::MethodObject<'tcx> {
1058     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1059         format!("MethodObject({},{},{})",
1060                 self.trait_ref.repr(tcx),
1061                 self.method_num,
1062                 self.real_index)
1063     }
1064 }
1065
1066 impl<'tcx> Repr<'tcx> for ty::TraitStore {
1067     fn repr(&self, tcx: &ctxt) -> String {
1068         trait_store_to_string(tcx, *self)
1069     }
1070 }
1071
1072 impl<'tcx> Repr<'tcx> for ty::BuiltinBound {
1073     fn repr(&self, _tcx: &ctxt) -> String {
1074         format!("{}", *self)
1075     }
1076 }
1077
1078 impl<'tcx> UserString<'tcx> for ty::BuiltinBound {
1079     fn user_string(&self, _tcx: &ctxt) -> String {
1080         match *self {
1081             ty::BoundSend => "Send".to_string(),
1082             ty::BoundSized => "Sized".to_string(),
1083             ty::BoundCopy => "Copy".to_string(),
1084             ty::BoundSync => "Sync".to_string(),
1085         }
1086     }
1087 }
1088
1089 impl<'tcx> Repr<'tcx> for Span {
1090     fn repr(&self, tcx: &ctxt) -> String {
1091         tcx.sess.codemap().span_to_string(*self).to_string()
1092     }
1093 }
1094
1095 impl<'tcx, A:UserString<'tcx>> UserString<'tcx> for Rc<A> {
1096     fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1097         let this: &A = &**self;
1098         this.user_string(tcx)
1099     }
1100 }
1101
1102 impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
1103     fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1104         let mut result = Vec::new();
1105         let s = self.builtin_bounds.user_string(tcx);
1106         if !s.is_empty() {
1107             result.push(s);
1108         }
1109         for n in self.trait_bounds.iter() {
1110             result.push(n.user_string(tcx));
1111         }
1112         result.connect("+")
1113     }
1114 }
1115
1116 impl<'tcx> UserString<'tcx> for ty::ExistentialBounds {
1117     fn user_string(&self, tcx: &ctxt) -> String {
1118         if self.builtin_bounds.contains(&ty::BoundSend) &&
1119             self.region_bound == ty::ReStatic
1120         { // Region bound is implied by builtin bounds:
1121             return self.builtin_bounds.repr(tcx);
1122         }
1123
1124         let mut res = Vec::new();
1125
1126         let region_str = self.region_bound.user_string(tcx);
1127         if !region_str.is_empty() {
1128             res.push(region_str);
1129         }
1130
1131         for bound in self.builtin_bounds.iter() {
1132             res.push(bound.user_string(tcx));
1133         }
1134
1135         res.connect("+")
1136     }
1137 }
1138
1139 impl<'tcx> UserString<'tcx> for ty::BuiltinBounds {
1140     fn user_string(&self, tcx: &ctxt) -> String {
1141         self.iter()
1142             .map(|bb| bb.user_string(tcx))
1143             .collect::<Vec<String>>()
1144             .connect("+")
1145             .to_string()
1146     }
1147 }
1148
1149 impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
1150     fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1151         // Replace any anonymous late-bound regions with named
1152         // variants, using gensym'd identifiers, so that we can
1153         // clearly differentiate between named and unnamed regions in
1154         // the output. We'll probably want to tweak this over time to
1155         // decide just how much information to give.
1156         let mut names = Vec::new();
1157         let (trait_ref, _) = ty::replace_late_bound_regions(tcx, self, |br, debruijn| {
1158             ty::ReLateBound(debruijn, match br {
1159                 ty::BrNamed(_, name) => {
1160                     names.push(token::get_name(name));
1161                     br
1162                 }
1163                 ty::BrAnon(_) |
1164                 ty::BrFresh(_) |
1165                 ty::BrEnv => {
1166                     let name = token::gensym("r");
1167                     names.push(token::get_name(name));
1168                     ty::BrNamed(ast_util::local_def(ast::DUMMY_NODE_ID), name)
1169                 }
1170             })
1171         });
1172         let names: Vec<_> = names.iter().map(|s| s.get()).collect();
1173
1174         // Let the base string be either `SomeTrait` for `for<'a,'b> SomeTrait`,
1175         // depending on whether there are bound regions.
1176         let path_str = ty::item_path_str(tcx, self.def_id);
1177         let base =
1178             if names.is_empty() {
1179                 path_str
1180             } else {
1181                 format!("for<{}> {}", names.connect(","), path_str)
1182             };
1183
1184         let trait_def = ty::lookup_trait_def(tcx, self.def_id);
1185         parameterized(tcx, base.as_slice(), &trait_ref.substs, &trait_def.generics)
1186     }
1187 }
1188
1189 impl<'tcx> UserString<'tcx> for Ty<'tcx> {
1190     fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
1191         ty_to_string(tcx, *self)
1192     }
1193 }
1194
1195 impl<'tcx> UserString<'tcx> for ast::Ident {
1196     fn user_string(&self, _tcx: &ctxt) -> String {
1197         token::get_name(self.name).get().to_string()
1198     }
1199 }
1200
1201 impl<'tcx> Repr<'tcx> for abi::Abi {
1202     fn repr(&self, _tcx: &ctxt) -> String {
1203         self.to_string()
1204     }
1205 }
1206
1207 impl<'tcx> UserString<'tcx> for abi::Abi {
1208     fn user_string(&self, _tcx: &ctxt) -> String {
1209         self.to_string()
1210     }
1211 }
1212
1213 impl<'tcx> Repr<'tcx> for ty::UpvarId {
1214     fn repr(&self, tcx: &ctxt) -> String {
1215         format!("UpvarId({};`{}`;{})",
1216                 self.var_id,
1217                 ty::local_var_name_str(tcx, self.var_id),
1218                 self.closure_expr_id)
1219     }
1220 }
1221
1222 impl<'tcx> Repr<'tcx> for ast::Mutability {
1223     fn repr(&self, _tcx: &ctxt) -> String {
1224         format!("{}", *self)
1225     }
1226 }
1227
1228 impl<'tcx> Repr<'tcx> for ty::BorrowKind {
1229     fn repr(&self, _tcx: &ctxt) -> String {
1230         format!("{}", *self)
1231     }
1232 }
1233
1234 impl<'tcx> Repr<'tcx> for ty::UpvarBorrow {
1235     fn repr(&self, tcx: &ctxt) -> String {
1236         format!("UpvarBorrow({}, {})",
1237                 self.kind.repr(tcx),
1238                 self.region.repr(tcx))
1239     }
1240 }
1241
1242 impl<'tcx> Repr<'tcx> for ty::IntVid {
1243     fn repr(&self, _tcx: &ctxt) -> String {
1244         format!("{}", self)
1245     }
1246 }
1247
1248 impl<'tcx> Repr<'tcx> for ty::FloatVid {
1249     fn repr(&self, _tcx: &ctxt) -> String {
1250         format!("{}", self)
1251     }
1252 }
1253
1254 impl<'tcx> Repr<'tcx> for ty::RegionVid {
1255     fn repr(&self, _tcx: &ctxt) -> String {
1256         format!("{}", self)
1257     }
1258 }
1259
1260 impl<'tcx> Repr<'tcx> for ty::TyVid {
1261     fn repr(&self, _tcx: &ctxt) -> String {
1262         format!("{}", self)
1263     }
1264 }
1265
1266 impl<'tcx> Repr<'tcx> for ty::IntVarValue {
1267     fn repr(&self, _tcx: &ctxt) -> String {
1268         format!("{}", *self)
1269     }
1270 }
1271
1272 impl<'tcx> Repr<'tcx> for ast::IntTy {
1273     fn repr(&self, _tcx: &ctxt) -> String {
1274         format!("{}", *self)
1275     }
1276 }
1277
1278 impl<'tcx> Repr<'tcx> for ast::UintTy {
1279     fn repr(&self, _tcx: &ctxt) -> String {
1280         format!("{}", *self)
1281     }
1282 }
1283
1284 impl<'tcx> Repr<'tcx> for ast::FloatTy {
1285     fn repr(&self, _tcx: &ctxt) -> String {
1286         format!("{}", *self)
1287     }
1288 }
1289
1290 impl<'tcx> Repr<'tcx> for ty::ExplicitSelfCategory {
1291     fn repr(&self, _: &ctxt) -> String {
1292         explicit_self_category_to_str(self).to_string()
1293     }
1294 }
1295
1296
1297 impl<'tcx> Repr<'tcx> for regionmanip::WfConstraint<'tcx> {
1298     fn repr(&self, tcx: &ctxt) -> String {
1299         match *self {
1300             regionmanip::RegionSubRegionConstraint(_, r_a, r_b) => {
1301                 format!("RegionSubRegionConstraint({}, {})",
1302                         r_a.repr(tcx),
1303                         r_b.repr(tcx))
1304             }
1305
1306             regionmanip::RegionSubParamConstraint(_, r, p) => {
1307                 format!("RegionSubParamConstraint({}, {})",
1308                         r.repr(tcx),
1309                         p.repr(tcx))
1310             }
1311         }
1312     }
1313 }
1314
1315 impl<'tcx> UserString<'tcx> for ParamTy {
1316     fn user_string(&self, tcx: &ctxt) -> String {
1317         let id = self.idx;
1318         let did = self.def_id;
1319         let ident = match tcx.ty_param_defs.borrow().get(&did.node) {
1320             Some(def) => token::get_name(def.name).get().to_string(),
1321
1322             // This can only happen when a type mismatch error happens and
1323             // the actual type has more type parameters than the expected one.
1324             None => format!("<generic #{}>", id),
1325         };
1326         ident
1327     }
1328 }
1329
1330 impl<'tcx> Repr<'tcx> for ParamTy {
1331     fn repr(&self, tcx: &ctxt) -> String {
1332         let ident = self.user_string(tcx);
1333         format!("{}/{}.{}", ident, self.space, self.idx)
1334     }
1335 }
1336
1337 impl<'tcx, A:Repr<'tcx>, B:Repr<'tcx>> Repr<'tcx> for (A,B) {
1338     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1339         let &(ref a, ref b) = self;
1340         format!("({},{})", a.repr(tcx), b.repr(tcx))
1341     }
1342 }
1343
1344 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for ty::Binder<T> {
1345     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
1346         format!("Binder({})", self.value.repr(tcx))
1347     }
1348 }