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