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