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