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