]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
8f0dd51457074c23bdd2e2a7cb219e4f8cd40301
[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 metadata::encoder;
13 use middle::ty::{ReSkolemized, ReVar};
14 use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
15 use middle::ty::{br_fresh, ctxt, field};
16 use middle::ty::{mt, t, param_ty};
17 use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region,
18                  re_empty};
19 use middle::ty::{ty_bool, ty_bot, ty_box, ty_struct, ty_enum};
20 use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure};
21 use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
22 use middle::ty::{ty_ptr, ty_rptr, ty_self, ty_tup, ty_type, ty_uniq};
23 use middle::ty::{ty_trait, ty_int};
24 use middle::ty::{ty_uint, ty_unboxed_vec, ty_infer};
25 use middle::ty;
26 use middle::typeck;
27 use syntax::abi::AbiSet;
28 use syntax::ast_map;
29 use syntax::codemap::span;
30 use syntax::parse::token;
31 use syntax::print::pprust;
32 use syntax::{ast, ast_util};
33 use syntax::opt_vec;
34 use syntax::opt_vec::OptVec;
35
36 /// Produces a string suitable for debugging output.
37 pub trait Repr {
38     fn repr(&self, tcx: ctxt) -> ~str;
39 }
40
41 /// Produces a string suitable for showing to the user.
42 pub trait UserString {
43     fn user_string(&self, tcx: ctxt) -> ~str;
44 }
45
46 pub fn note_and_explain_region(cx: ctxt,
47                                prefix: &str,
48                                region: ty::Region,
49                                suffix: &str) {
50     match explain_region_and_span(cx, region) {
51       (ref str, Some(span)) => {
52         cx.sess.span_note(
53             span,
54             fmt!("%s%s%s", prefix, (*str), suffix));
55       }
56       (ref str, None) => {
57         cx.sess.note(
58             fmt!("%s%s%s", prefix, (*str), suffix));
59       }
60     }
61 }
62
63 /// Returns a string like "the block at 27:31" that attempts to explain a
64 /// lifetime in a way it might plausibly be understood.
65 pub fn explain_region(cx: ctxt, region: ty::Region) -> ~str {
66   let (res, _) = explain_region_and_span(cx, region);
67   return res;
68 }
69
70
71 pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
72                             -> (~str, Option<span>) {
73     return match region {
74       re_scope(node_id) => {
75         match cx.items.find(&node_id) {
76           Some(&ast_map::node_block(ref blk)) => {
77             explain_span(cx, "block", blk.span)
78           }
79           Some(&ast_map::node_callee_scope(expr)) => {
80               explain_span(cx, "callee", expr.span)
81           }
82           Some(&ast_map::node_expr(expr)) => {
83             match expr.node {
84               ast::expr_call(*) => explain_span(cx, "call", expr.span),
85               ast::expr_method_call(*) => {
86                 explain_span(cx, "method call", expr.span)
87               },
88               ast::expr_match(*) => explain_span(cx, "match", expr.span),
89               _ => explain_span(cx, "expression", expr.span)
90             }
91           }
92           Some(&ast_map::node_stmt(stmt)) => {
93               explain_span(cx, "statement", stmt.span)
94           }
95           Some(&ast_map::node_item(it, _)) if (match it.node {
96                 ast::item_fn(*) => true, _ => false}) => {
97               explain_span(cx, "function body", it.span)
98           }
99           Some(_) | None => {
100             // this really should not happen
101             (fmt!("unknown scope: %d.  Please report a bug.", node_id),
102              None)
103           }
104         }
105       }
106
107       re_free(ref fr) => {
108         let prefix = match fr.bound_region {
109           br_anon(idx) => fmt!("the anonymous lifetime #%u defined on",
110                                idx + 1),
111           br_fresh(_) => fmt!("an anonymous lifetime defined on"),
112           _ => fmt!("the lifetime %s as defined on",
113                     bound_region_ptr_to_str(cx, fr.bound_region))
114         };
115
116         match cx.items.find(&fr.scope_id) {
117           Some(&ast_map::node_block(ref blk)) => {
118             let (msg, opt_span) = explain_span(cx, "block", blk.span);
119             (fmt!("%s %s", prefix, msg), opt_span)
120           }
121           Some(_) | None => {
122             // this really should not happen
123             (fmt!("%s node %d", prefix, fr.scope_id), None)
124           }
125         }
126       }
127
128       re_static => { (~"the static lifetime", None) }
129
130       re_empty => { (~"the empty lifetime", None) }
131
132       // I believe these cases should not occur (except when debugging,
133       // perhaps)
134       re_infer(_) | re_bound(_) => {
135         (fmt!("lifetime %?", region), None)
136       }
137     };
138
139     fn explain_span(cx: ctxt, heading: &str, span: span)
140         -> (~str, Option<span>)
141     {
142         let lo = cx.sess.codemap.lookup_char_pos_adj(span.lo);
143         (fmt!("the %s at %u:%u", heading,
144               lo.line, lo.col.to_uint()), Some(span))
145     }
146 }
147
148 pub fn bound_region_ptr_to_str(cx: ctxt, br: bound_region) -> ~str {
149     bound_region_to_str(cx, "&", true, br)
150 }
151
152 pub fn bound_region_to_str(cx: ctxt,
153                            prefix: &str, space: bool,
154                            br: bound_region) -> ~str {
155     let space_str = if space { " " } else { "" };
156
157     if cx.sess.verbose() { return fmt!("%s%?%s", prefix, br, space_str); }
158
159     match br {
160       br_named(id)         => fmt!("%s'%s%s", prefix, cx.sess.str_of(id), space_str),
161       br_self              => fmt!("%s'self%s", prefix, space_str),
162       br_anon(_)           => prefix.to_str(),
163       br_fresh(_)          => prefix.to_str(),
164       br_cap_avoid(_, br)  => bound_region_to_str(cx, prefix, space, *br)
165     }
166 }
167
168 pub fn re_scope_id_to_str(cx: ctxt, node_id: ast::NodeId) -> ~str {
169     match cx.items.find(&node_id) {
170       Some(&ast_map::node_block(ref blk)) => {
171         fmt!("<block at %s>",
172              cx.sess.codemap.span_to_str(blk.span))
173       }
174       Some(&ast_map::node_expr(expr)) => {
175         match expr.node {
176           ast::expr_call(*) => {
177             fmt!("<call at %s>",
178                  cx.sess.codemap.span_to_str(expr.span))
179           }
180           ast::expr_match(*) => {
181             fmt!("<match at %s>",
182                  cx.sess.codemap.span_to_str(expr.span))
183           }
184           ast::expr_assign_op(*) |
185           ast::expr_unary(*) |
186           ast::expr_binary(*) |
187           ast::expr_index(*) => {
188             fmt!("<method at %s>",
189                  cx.sess.codemap.span_to_str(expr.span))
190           }
191           _ => {
192             fmt!("<expression at %s>",
193                  cx.sess.codemap.span_to_str(expr.span))
194           }
195         }
196       }
197       None => {
198         fmt!("<unknown-%d>", node_id)
199       }
200       _ => { cx.sess.bug(
201           fmt!("re_scope refers to %s",
202                ast_map::node_id_to_str(cx.items, node_id,
203                                        token::get_ident_interner()))) }
204     }
205 }
206
207 // In general, if you are giving a region error message,
208 // you should use `explain_region()` or, better yet,
209 // `note_and_explain_region()`
210 pub fn region_ptr_to_str(cx: ctxt, region: Region) -> ~str {
211     region_to_str(cx, "&", true, region)
212 }
213
214 pub fn region_to_str(cx: ctxt, prefix: &str, space: bool, region: Region) -> ~str {
215     let space_str = if space { " " } else { "" };
216
217     if cx.sess.verbose() {
218         return fmt!("%s%?%s", prefix, region, space_str);
219     }
220
221     // These printouts are concise.  They do not contain all the information
222     // the user might want to diagnose an error, but there is basically no way
223     // to fit that into a short string.  Hence the recommendation to use
224     // `explain_region()` or `note_and_explain_region()`.
225     match region {
226         re_scope(_) => prefix.to_str(),
227         re_bound(br) => bound_region_to_str(cx, prefix, space, br),
228         re_free(ref fr) => bound_region_to_str(cx, prefix, space, fr.bound_region),
229         re_infer(ReSkolemized(_, br)) => {
230             bound_region_to_str(cx, prefix, space, br)
231         }
232         re_infer(ReVar(_)) => prefix.to_str(),
233         re_static => fmt!("%s'static%s", prefix, space_str),
234         re_empty => fmt!("%s'<empty>%s", prefix, space_str)
235     }
236 }
237
238 fn mutability_to_str(m: ast::mutability) -> ~str {
239     match m {
240         ast::m_mutbl => ~"mut ",
241         ast::m_imm => ~"",
242         ast::m_const => ~"const "
243     }
244 }
245
246 pub fn mt_to_str(cx: ctxt, m: &mt) -> ~str {
247     mt_to_str_wrapped(cx, "", m, "")
248 }
249
250 pub fn mt_to_str_wrapped(cx: ctxt, before: &str, m: &mt, after: &str) -> ~str {
251     let mstr = mutability_to_str(m.mutbl);
252     return fmt!("%s%s%s%s", mstr, before, ty_to_str(cx, m.ty), after);
253 }
254
255 pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
256     match vs {
257       ty::vstore_fixed(n) => fmt!("%u", n),
258       ty::vstore_uniq => ~"~",
259       ty::vstore_box => ~"@",
260       ty::vstore_slice(r) => region_ptr_to_str(cx, r)
261     }
262 }
263
264 pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str {
265     match s {
266       ty::UniqTraitStore => ~"~",
267       ty::BoxTraitStore => ~"@",
268       ty::RegionTraitStore(r) => region_ptr_to_str(cx, r)
269     }
270 }
271
272 pub fn vstore_ty_to_str(cx: ctxt, mt: &mt, vs: ty::vstore) -> ~str {
273     match vs {
274         ty::vstore_fixed(_) => {
275             fmt!("[%s, .. %s]", mt_to_str(cx, mt), vstore_to_str(cx, vs))
276         }
277         _ => {
278             fmt!("%s%s", vstore_to_str(cx, vs), mt_to_str_wrapped(cx, "[", mt, "]"))
279         }
280     }
281 }
282
283 pub fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str {
284     let tstrs = ts.map(|t| ty_to_str(cx, *t));
285     fmt!("(%s)", tstrs.connect(", "))
286 }
287
288 pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
289     fmt!("fn%s -> %s",
290          tys_to_str(cx, typ.inputs.map(|a| *a)),
291          ty_to_str(cx, typ.output))
292 }
293
294 pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str {
295     trait_ref.user_string(cx)
296 }
297
298 pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
299     fn fn_input_to_str(cx: ctxt, input: ty::t) -> ~str {
300         ty_to_str(cx, input)
301     }
302     fn bare_fn_to_str(cx: ctxt,
303                       purity: ast::purity,
304                       abis: AbiSet,
305                       ident: Option<ast::ident>,
306                       sig: &ty::FnSig)
307                       -> ~str {
308         let mut s = ~"extern ";
309
310         s.push_str(abis.to_str());
311         s.push_char(' ');
312
313         match purity {
314             ast::impure_fn => {}
315             _ => {
316                 s.push_str(purity.to_str());
317                 s.push_char(' ');
318             }
319         };
320
321         s.push_str("fn");
322
323         match ident {
324           Some(i) => {
325               s.push_char(' ');
326               s.push_str(cx.sess.str_of(i));
327           }
328           _ => { }
329         }
330
331         push_sig_to_str(cx, &mut s, sig);
332
333         return s;
334     }
335     fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str
336     {
337         let mut s = cty.sigil.to_str();
338
339         match (cty.sigil, cty.region) {
340             (ast::ManagedSigil, ty::re_static) |
341             (ast::OwnedSigil, ty::re_static) => {}
342
343             (_, region) => {
344                 s.push_str(region_to_str(cx, "", true, region));
345             }
346         }
347
348         match cty.purity {
349             ast::impure_fn => {}
350             _ => {
351                 s.push_str(cty.purity.to_str());
352                 s.push_char(' ');
353             }
354         };
355
356         match cty.onceness {
357             ast::Many => {}
358             ast::Once => {
359                 s.push_str(cty.onceness.to_str());
360                 s.push_char(' ');
361             }
362         };
363
364         s.push_str("fn");
365
366         if !cty.bounds.is_empty() {
367             s.push_str(":");
368         }
369         s.push_str(cty.bounds.repr(cx));
370
371         push_sig_to_str(cx, &mut s, &cty.sig);
372
373         return s;
374     }
375     fn push_sig_to_str(cx: ctxt, s: &mut ~str, sig: &ty::FnSig) {
376         s.push_char('(');
377         let strs = sig.inputs.map(|a| fn_input_to_str(cx, *a));
378         s.push_str(strs.connect(", "));
379         s.push_char(')');
380         if ty::get(sig.output).sty != ty_nil {
381             s.push_str(" -> ");
382             if ty::type_is_bot(sig.output) {
383                 s.push_char('!');
384             } else {
385                 s.push_str(ty_to_str(cx, sig.output));
386             }
387         }
388     }
389     fn method_to_str(cx: ctxt, m: ty::Method) -> ~str {
390         bare_fn_to_str(cx,
391                        m.fty.purity,
392                        m.fty.abis,
393                        Some(m.ident),
394                        &m.fty.sig) + ";"
395     }
396     fn field_to_str(cx: ctxt, f: field) -> ~str {
397         return fmt!("%s: %s", cx.sess.str_of(f.ident), mt_to_str(cx, &f.mt));
398     }
399
400     // if there is an id, print that instead of the structural type:
401     /*for def_id in ty::type_def_id(typ).iter() {
402         // note that this typedef cannot have type parameters
403         return ast_map::path_to_str(ty::item_path(cx, *def_id),
404                                     cx.sess.intr());
405     }*/
406
407     // pretty print the structural type representation:
408     return match ty::get(typ).sty {
409       ty_nil => ~"()",
410       ty_bot => ~"!",
411       ty_bool => ~"bool",
412       ty_int(ast::ty_i) => ~"int",
413       ty_int(ast::ty_char) => ~"char",
414       ty_int(t) => ast_util::int_ty_to_str(t),
415       ty_uint(ast::ty_u) => ~"uint",
416       ty_uint(t) => ast_util::uint_ty_to_str(t),
417       ty_float(ast::ty_f) => ~"float",
418       ty_float(t) => ast_util::float_ty_to_str(t),
419       ty_box(ref tm) => ~"@" + mt_to_str(cx, tm),
420       ty_uniq(ref tm) => ~"~" + mt_to_str(cx, tm),
421       ty_ptr(ref tm) => ~"*" + mt_to_str(cx, tm),
422       ty_rptr(r, ref tm) => {
423         region_ptr_to_str(cx, r) + mt_to_str(cx, tm)
424       }
425       ty_unboxed_vec(ref tm) => { fmt!("unboxed_vec<%s>", mt_to_str(cx, tm)) }
426       ty_type => ~"type",
427       ty_tup(ref elems) => {
428         let strs = elems.map(|elem| ty_to_str(cx, *elem));
429         ~"(" + strs.connect(",") + ")"
430       }
431       ty_closure(ref f) => {
432           closure_to_str(cx, f)
433       }
434       ty_bare_fn(ref f) => {
435           bare_fn_to_str(cx, f.purity, f.abis, None, &f.sig)
436       }
437       ty_infer(infer_ty) => infer_ty.to_str(),
438       ty_err => ~"[type error]",
439       ty_param(param_ty {idx: id, def_id: did}) => {
440           let param_def = cx.ty_param_defs.find(&did.node);
441           let ident = match param_def {
442               Some(def) => {
443                   cx.sess.str_of(def.ident).to_owned()
444               }
445               None => {
446                   // This should not happen...
447                   fmt!("BUG[%?]", id)
448               }
449           };
450           if !cx.sess.verbose() { ident } else { fmt!("%s:%?", ident, did) }
451       }
452       ty_self(*) => ~"Self",
453       ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
454         let path = ty::item_path(cx, did);
455         let base = ast_map::path_to_str(path, cx.sess.intr());
456         parameterized(cx, base, &substs.regions, substs.tps)
457       }
458       ty_trait(did, ref substs, s, mutbl, ref bounds) => {
459         let path = ty::item_path(cx, did);
460         let base = ast_map::path_to_str(path, cx.sess.intr());
461         let ty = parameterized(cx, base, &substs.regions, substs.tps);
462         let bound_sep = if bounds.is_empty() { "" } else { ":" };
463         let bound_str = bounds.repr(cx);
464         fmt!("%s%s%s%s%s", trait_store_to_str(cx, s), mutability_to_str(mutbl), ty,
465                            bound_sep, bound_str)
466       }
467       ty_evec(ref mt, vs) => {
468         vstore_ty_to_str(cx, mt, vs)
469       }
470       ty_estr(vs) => fmt!("%s%s", vstore_to_str(cx, vs), "str"),
471       ty_opaque_box => ~"@?",
472       ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"&closure",
473       ty_opaque_closure_ptr(ast::ManagedSigil) => ~"@closure",
474       ty_opaque_closure_ptr(ast::OwnedSigil) => ~"~closure",
475     }
476 }
477
478 pub fn parameterized(cx: ctxt,
479                      base: &str,
480                      regions: &ty::RegionSubsts,
481                      tps: &[ty::t]) -> ~str {
482
483     let mut strs = ~[];
484     match *regions {
485         ty::ErasedRegions => { }
486         ty::NonerasedRegions(ref regions) => {
487             for &r in regions.iter() {
488                 strs.push(region_to_str(cx, "", false, r))
489             }
490         }
491     }
492
493     for t in tps.iter() {
494         strs.push(ty_to_str(cx, *t))
495     }
496
497     if strs.len() > 0u {
498         fmt!("%s<%s>", base, strs.connect(","))
499     } else {
500         fmt!("%s", base)
501     }
502 }
503
504 pub fn ty_to_short_str(cx: ctxt, typ: t) -> ~str {
505     let mut s = encoder::encoded_ty(cx, typ);
506     if s.len() >= 32u { s = s.slice(0u, 32u).to_owned(); }
507     return s;
508 }
509
510 impl<T:Repr> Repr for Option<T> {
511     fn repr(&self, tcx: ctxt) -> ~str {
512         match self {
513             &None => ~"None",
514             &Some(ref t) => fmt!("Some(%s)", t.repr(tcx))
515         }
516     }
517 }
518
519 impl<T:Repr> Repr for @T {
520     fn repr(&self, tcx: ctxt) -> ~str {
521         (&**self).repr(tcx)
522     }
523 }
524
525 impl<T:Repr> Repr for ~T {
526     fn repr(&self, tcx: ctxt) -> ~str {
527         (&**self).repr(tcx)
528     }
529 }
530
531 fn repr_vec<T:Repr>(tcx: ctxt, v: &[T]) -> ~str {
532     fmt!("[%s]", v.map(|t| t.repr(tcx)).connect(","))
533 }
534
535 impl<'self, T:Repr> Repr for &'self [T] {
536     fn repr(&self, tcx: ctxt) -> ~str {
537         repr_vec(tcx, *self)
538     }
539 }
540
541 impl<T:Repr> Repr for OptVec<T> {
542     fn repr(&self, tcx: ctxt) -> ~str {
543         match *self {
544             opt_vec::Empty => ~"[]",
545             opt_vec::Vec(ref v) => repr_vec(tcx, *v)
546         }
547     }
548 }
549
550 // This is necessary to handle types like Option<~[T]>, for which
551 // autoderef cannot convert the &[T] handler
552 impl<T:Repr> Repr for ~[T] {
553     fn repr(&self, tcx: ctxt) -> ~str {
554         repr_vec(tcx, *self)
555     }
556 }
557
558 impl Repr for ty::TypeParameterDef {
559     fn repr(&self, tcx: ctxt) -> ~str {
560         fmt!("TypeParameterDef {%?, bounds: %s}",
561              self.def_id, self.bounds.repr(tcx))
562     }
563 }
564
565 impl Repr for ty::t {
566     fn repr(&self, tcx: ctxt) -> ~str {
567         ty_to_str(tcx, *self)
568     }
569 }
570
571 impl Repr for ty::substs {
572     fn repr(&self, tcx: ctxt) -> ~str {
573         fmt!("substs(regions=%s, self_ty=%s, tps=%s)",
574              self.regions.repr(tcx),
575              self.self_ty.repr(tcx),
576              self.tps.repr(tcx))
577     }
578 }
579
580 impl Repr for ty::RegionSubsts {
581     fn repr(&self, tcx: ctxt) -> ~str {
582         match *self {
583             ty::ErasedRegions => ~"erased",
584             ty::NonerasedRegions(ref regions) => regions.repr(tcx)
585         }
586     }
587 }
588
589 impl Repr for ty::ParamBounds {
590     fn repr(&self, tcx: ctxt) -> ~str {
591         let mut res = ~[];
592         do self.builtin_bounds.each |b| {
593             res.push(match b {
594                 ty::BoundStatic => ~"'static",
595                 ty::BoundSend => ~"Send",
596                 ty::BoundFreeze => ~"Freeze",
597                 ty::BoundSized => ~"Sized",
598             });
599             true
600         };
601         for t in self.trait_bounds.iter() {
602             res.push(t.repr(tcx));
603         }
604         res.connect("+")
605     }
606 }
607
608 impl Repr for ty::TraitRef {
609     fn repr(&self, tcx: ctxt) -> ~str {
610         trait_ref_to_str(tcx, self)
611     }
612 }
613
614 impl Repr for ast::expr {
615     fn repr(&self, tcx: ctxt) -> ~str {
616         fmt!("expr(%d: %s)",
617              self.id,
618              pprust::expr_to_str(self, tcx.sess.intr()))
619     }
620 }
621
622 impl Repr for ast::pat {
623     fn repr(&self, tcx: ctxt) -> ~str {
624         fmt!("pat(%d: %s)",
625              self.id,
626              pprust::pat_to_str(self, tcx.sess.intr()))
627     }
628 }
629
630 impl Repr for ty::bound_region {
631     fn repr(&self, tcx: ctxt) -> ~str {
632         bound_region_ptr_to_str(tcx, *self)
633     }
634 }
635
636 impl Repr for ty::Region {
637     fn repr(&self, tcx: ctxt) -> ~str {
638         region_to_str(tcx, "", false, *self)
639     }
640 }
641
642 impl Repr for ast::def_id {
643     fn repr(&self, tcx: ctxt) -> ~str {
644         // Unfortunately, there seems to be no way to attempt to print
645         // a path for a def-id, so I'll just make a best effort for now
646         // and otherwise fallback to just printing the crate/node pair
647         if self.crate == ast::LOCAL_CRATE {
648             match tcx.items.find(&self.node) {
649                 Some(&ast_map::node_item(*)) |
650                 Some(&ast_map::node_foreign_item(*)) |
651                 Some(&ast_map::node_method(*)) |
652                 Some(&ast_map::node_trait_method(*)) |
653                 Some(&ast_map::node_variant(*)) |
654                 Some(&ast_map::node_struct_ctor(*)) => {
655                     return fmt!("%?:%s", *self, ty::item_path_str(tcx, *self));
656                 }
657                 _ => {}
658             }
659         }
660         return fmt!("%?", *self);
661     }
662 }
663
664 impl Repr for ty::ty_param_bounds_and_ty {
665     fn repr(&self, tcx: ctxt) -> ~str {
666         fmt!("ty_param_bounds_and_ty {generics: %s, ty: %s}",
667              self.generics.repr(tcx),
668              self.ty.repr(tcx))
669     }
670 }
671
672 impl Repr for ty::Generics {
673     fn repr(&self, tcx: ctxt) -> ~str {
674         fmt!("Generics {type_param_defs: %s, region_param: %?}",
675              self.type_param_defs.repr(tcx),
676              self.region_param)
677     }
678 }
679
680 impl Repr for ty::Method {
681     fn repr(&self, tcx: ctxt) -> ~str {
682         fmt!("method {ident: %s, generics: %s, transformed_self_ty: %s, \
683               fty: %s, explicit_self: %s, vis: %s, def_id: %s}",
684              self.ident.repr(tcx),
685              self.generics.repr(tcx),
686              self.transformed_self_ty.repr(tcx),
687              self.fty.repr(tcx),
688              self.explicit_self.repr(tcx),
689              self.vis.repr(tcx),
690              self.def_id.repr(tcx))
691     }
692 }
693
694 impl Repr for ast::ident {
695     fn repr(&self, _tcx: ctxt) -> ~str {
696         token::ident_to_str(self).to_owned()
697     }
698 }
699
700 impl Repr for ast::explicit_self_ {
701     fn repr(&self, _tcx: ctxt) -> ~str {
702         fmt!("%?", *self)
703     }
704 }
705
706 impl Repr for ast::visibility {
707     fn repr(&self, _tcx: ctxt) -> ~str {
708         fmt!("%?", *self)
709     }
710 }
711
712 impl Repr for ty::BareFnTy {
713     fn repr(&self, tcx: ctxt) -> ~str {
714         fmt!("BareFnTy {purity: %?, abis: %s, sig: %s}",
715              self.purity,
716              self.abis.to_str(),
717              self.sig.repr(tcx))
718     }
719 }
720
721 impl Repr for ty::FnSig {
722     fn repr(&self, tcx: ctxt) -> ~str {
723         fn_sig_to_str(tcx, self)
724     }
725 }
726
727 impl Repr for typeck::method_map_entry {
728     fn repr(&self, tcx: ctxt) -> ~str {
729         fmt!("method_map_entry {self_arg: %s, \
730               explicit_self: %s, \
731               origin: %s}",
732              self.self_ty.repr(tcx),
733              self.explicit_self.repr(tcx),
734              self.origin.repr(tcx))
735     }
736 }
737
738 impl Repr for typeck::method_origin {
739     fn repr(&self, tcx: ctxt) -> ~str {
740         match self {
741             &typeck::method_static(def_id) => {
742                 fmt!("method_static(%s)", def_id.repr(tcx))
743             }
744             &typeck::method_param(ref p) => {
745                 p.repr(tcx)
746             }
747             &typeck::method_trait(def_id, n, st) => {
748                 fmt!("method_trait(%s, %?, %s)", def_id.repr(tcx), n,
749                      st.repr(tcx))
750             }
751         }
752     }
753 }
754
755 impl Repr for typeck::method_param {
756     fn repr(&self, tcx: ctxt) -> ~str {
757         fmt!("method_param(%s,%?,%?,%?)",
758              self.trait_id.repr(tcx),
759              self.method_num,
760              self.param_num,
761              self.bound_num)
762     }
763 }
764
765 impl Repr for ty::RegionVid {
766     fn repr(&self, _tcx: ctxt) -> ~str {
767         fmt!("%?", *self)
768     }
769 }
770
771 impl Repr for ty::TraitStore {
772     fn repr(&self, tcx: ctxt) -> ~str {
773         match self {
774             &ty::BoxTraitStore => ~"@Trait",
775             &ty::UniqTraitStore => ~"~Trait",
776             &ty::RegionTraitStore(r) => fmt!("&%s Trait", r.repr(tcx))
777         }
778     }
779 }
780
781 impl Repr for ty::vstore {
782     fn repr(&self, tcx: ctxt) -> ~str {
783         vstore_to_str(tcx, *self)
784     }
785 }
786
787 impl Repr for ast_map::path_elt {
788     fn repr(&self, tcx: ctxt) -> ~str {
789         match *self {
790             ast_map::path_mod(id) => id.repr(tcx),
791             ast_map::path_name(id) => id.repr(tcx)
792         }
793     }
794 }
795
796 impl Repr for ty::BuiltinBound {
797     fn repr(&self, _tcx: ctxt) -> ~str {
798         fmt!("%?", *self)
799     }
800 }
801
802 impl UserString for ty::BuiltinBound {
803     fn user_string(&self, _tcx: ctxt) -> ~str {
804         match *self {
805             ty::BoundStatic => ~"'static",
806             ty::BoundSend => ~"Send",
807             ty::BoundFreeze => ~"Freeze",
808             ty::BoundSized => ~"Sized",
809         }
810     }
811 }
812
813 impl Repr for ty::BuiltinBounds {
814     fn repr(&self, tcx: ctxt) -> ~str {
815         self.user_string(tcx)
816     }
817 }
818
819 impl Repr for span {
820     fn repr(&self, tcx: ctxt) -> ~str {
821         tcx.sess.codemap.span_to_str(*self)
822     }
823 }
824
825 impl<A:UserString> UserString for @A {
826     fn user_string(&self, tcx: ctxt) -> ~str {
827         let this: &A = &**self;
828         this.user_string(tcx)
829     }
830 }
831
832 impl UserString for ty::BuiltinBounds {
833     fn user_string(&self, tcx: ctxt) -> ~str {
834         if self.is_empty() { ~"<no-bounds>" } else {
835             let mut result = ~[];
836             do self.each |bb| {
837                 result.push(bb.user_string(tcx));
838                 true
839             };
840             result.connect("+")
841         }
842     }
843 }
844
845 impl UserString for ty::TraitRef {
846     fn user_string(&self, tcx: ctxt) -> ~str {
847         let path = ty::item_path(tcx, self.def_id);
848         let base = ast_map::path_to_str(path, tcx.sess.intr());
849         if tcx.sess.verbose() && self.substs.self_ty.is_some() {
850             let mut all_tps = self.substs.tps.clone();
851             for &t in self.substs.self_ty.iter() { all_tps.push(t); }
852             parameterized(tcx, base, &self.substs.regions, all_tps)
853         } else {
854             parameterized(tcx, base, &self.substs.regions, self.substs.tps)
855         }
856     }
857 }
858
859 impl UserString for ty::t {
860     fn user_string(&self, tcx: ctxt) -> ~str {
861         ty_to_str(tcx, *self)
862     }
863 }