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