]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
Auto merge of #27983 - barosl:respect-color, r=nrc
[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_id::DefId;
13 use middle::subst::{self, Subst};
14 use middle::ty::{BoundRegion, BrAnon, BrNamed};
15 use middle::ty::{ReEarlyBound, BrFresh, ctxt};
16 use middle::ty::{ReFree, ReScope, ReStatic, Region, ReEmpty};
17 use middle::ty::{ReSkolemized, ReVar, BrEnv};
18 use middle::ty::{TyBool, TyChar, TyStruct, TyEnum};
19 use middle::ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyBareFn};
20 use middle::ty::{TyParam, TyRawPtr, TyRef, TyTuple};
21 use middle::ty::TyClosure;
22 use middle::ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
23 use middle::ty::{self, TypeAndMut, Ty, HasTypeFlags};
24 use middle::ty_fold::{self, TypeFoldable};
25
26 use std::fmt;
27 use syntax::abi;
28 use syntax::parse::token;
29 use syntax::{ast, ast_util};
30
31 pub fn verbose() -> bool {
32     ty::tls::with(|tcx| tcx.sess.verbose())
33 }
34
35 fn fn_sig(f: &mut fmt::Formatter,
36           inputs: &[Ty],
37           variadic: bool,
38           output: ty::FnOutput)
39           -> fmt::Result {
40     try!(write!(f, "("));
41     let mut inputs = inputs.iter();
42     if let Some(&ty) = inputs.next() {
43         try!(write!(f, "{}", ty));
44         for &ty in inputs {
45             try!(write!(f, ", {}", ty));
46         }
47         if variadic {
48             try!(write!(f, ", ..."));
49         }
50     }
51     try!(write!(f, ")"));
52
53     match output {
54         ty::FnConverging(ty) => {
55             if !ty.is_nil() {
56                 try!(write!(f, " -> {}", ty));
57             }
58             Ok(())
59         }
60         ty::FnDiverging => {
61             write!(f, " -> !")
62         }
63     }
64 }
65
66 fn parameterized<GG>(f: &mut fmt::Formatter,
67                      substs: &subst::Substs,
68                      did: DefId,
69                      projections: &[ty::ProjectionPredicate],
70                      get_generics: GG)
71                      -> fmt::Result
72     where GG: for<'tcx> FnOnce(&ty::ctxt<'tcx>) -> ty::Generics<'tcx>
73 {
74     let (fn_trait_kind, verbose) = try!(ty::tls::with(|tcx| {
75         try!(write!(f, "{}", tcx.item_path_str(did)));
76         Ok((tcx.lang_items.fn_trait_kind(did), tcx.sess.verbose()))
77     }));
78
79     let mut empty = true;
80     let mut start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| {
81         if empty {
82             empty = false;
83             write!(f, "{}", start)
84         } else {
85             write!(f, "{}", cont)
86         }
87     };
88
89     if verbose {
90         match substs.regions {
91             subst::ErasedRegions => {
92                 try!(start_or_continue(f, "<", ", "));
93                 try!(write!(f, ".."));
94             }
95             subst::NonerasedRegions(ref regions) => {
96                 for region in regions {
97                     try!(start_or_continue(f, "<", ", "));
98                     try!(write!(f, "{:?}", region));
99                 }
100             }
101         }
102         for &ty in &substs.types {
103             try!(start_or_continue(f, "<", ", "));
104             try!(write!(f, "{}", ty));
105         }
106         for projection in projections {
107             try!(start_or_continue(f, "<", ", "));
108             try!(write!(f, "{}={}",
109                         projection.projection_ty.item_name,
110                         projection.ty));
111         }
112         return start_or_continue(f, "", ">");
113     }
114
115     if fn_trait_kind.is_some() && projections.len() == 1 {
116         let projection_ty = projections[0].ty;
117         if let TyTuple(ref args) = substs.types.get_slice(subst::TypeSpace)[0].sty {
118             return fn_sig(f, args, false, ty::FnConverging(projection_ty));
119         }
120     }
121
122     match substs.regions {
123         subst::ErasedRegions => { }
124         subst::NonerasedRegions(ref regions) => {
125             for &r in regions {
126                 try!(start_or_continue(f, "<", ", "));
127                 let s = r.to_string();
128                 if s.is_empty() {
129                     // This happens when the value of the region
130                     // parameter is not easily serialized. This may be
131                     // because the user omitted it in the first place,
132                     // or because it refers to some block in the code,
133                     // etc. I'm not sure how best to serialize this.
134                     try!(write!(f, "'_"));
135                 } else {
136                     try!(write!(f, "{}", s));
137                 }
138             }
139         }
140     }
141
142     // It is important to execute this conditionally, only if -Z
143     // verbose is false. Otherwise, debug logs can sometimes cause
144     // ICEs trying to fetch the generics early in the pipeline. This
145     // is kind of a hacky workaround in that -Z verbose is required to
146     // avoid those ICEs.
147     let tps = substs.types.get_slice(subst::TypeSpace);
148     let num_defaults = ty::tls::with(|tcx| {
149         let generics = get_generics(tcx);
150
151         let has_self = substs.self_ty().is_some();
152         let ty_params = generics.types.get_slice(subst::TypeSpace);
153         if ty_params.last().map_or(false, |def| def.default.is_some()) {
154             let substs = tcx.lift(&substs);
155             ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| {
156                 match def.default {
157                     Some(default) => {
158                         if !has_self && default.has_self_ty() {
159                             // In an object type, there is no `Self`, and
160                             // thus if the default value references Self,
161                             // the user will be required to give an
162                             // explicit value. We can't even do the
163                             // substitution below to check without causing
164                             // an ICE. (#18956).
165                             false
166                         } else {
167                             let default = tcx.lift(&default);
168                             substs.and_then(|substs| default.subst(tcx, substs)) == Some(actual)
169                         }
170                     }
171                     None => false
172                 }
173             }).count()
174         } else {
175             0
176         }
177     });
178
179     for &ty in &tps[..tps.len() - num_defaults] {
180         try!(start_or_continue(f, "<", ", "));
181         try!(write!(f, "{}", ty));
182     }
183
184     for projection in projections {
185         try!(start_or_continue(f, "<", ", "));
186         try!(write!(f, "{}={}",
187                     projection.projection_ty.item_name,
188                     projection.ty));
189     }
190
191     start_or_continue(f, "", ">")
192 }
193
194 fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter,
195                          tcx: &ty::ctxt<'tcx>,
196                          original: &ty::Binder<T>,
197                          lifted: Option<ty::Binder<U>>) -> fmt::Result
198     where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx>
199 {
200     // Replace any anonymous late-bound regions with named
201     // variants, using gensym'd identifiers, so that we can
202     // clearly differentiate between named and unnamed regions in
203     // the output. We'll probably want to tweak this over time to
204     // decide just how much information to give.
205     let value = if let Some(v) = lifted {
206         v
207     } else {
208         return write!(f, "{}", original.0);
209     };
210
211     let mut empty = true;
212     let mut start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| {
213         if empty {
214             empty = false;
215             write!(f, "{}", start)
216         } else {
217             write!(f, "{}", cont)
218         }
219     };
220
221     let new_value = ty_fold::replace_late_bound_regions(tcx, &value, |br| {
222         let _ = start_or_continue(f, "for<", ", ");
223         ty::ReLateBound(ty::DebruijnIndex::new(1), match br {
224             ty::BrNamed(_, name) => {
225                 let _ = write!(f, "{}", name);
226                 br
227             }
228             ty::BrAnon(_) |
229             ty::BrFresh(_) |
230             ty::BrEnv => {
231                 let name = token::intern("'r");
232                 let _ = write!(f, "{}", name);
233                 ty::BrNamed(DefId::local(ast::DUMMY_NODE_ID), name)
234             }
235         })
236     }).0;
237
238     try!(start_or_continue(f, "", "> "));
239     write!(f, "{}", new_value)
240 }
241
242 /// This curious type is here to help pretty-print trait objects. In
243 /// a trait object, the projections are stored separately from the
244 /// main trait bound, but in fact we want to package them together
245 /// when printing out; they also have separate binders, but we want
246 /// them to share a binder when we print them out. (And the binder
247 /// pretty-printing logic is kind of clever and we don't want to
248 /// reproduce it.) So we just repackage up the structure somewhat.
249 ///
250 /// Right now there is only one trait in an object that can have
251 /// projection bounds, so we just stuff them altogether. But in
252 /// reality we should eventually sort things out better.
253 #[derive(Clone, Debug)]
254 struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec<ty::ProjectionPredicate<'tcx>>);
255
256 impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
257     fn fold_with<F:ty_fold::TypeFolder<'tcx>>(&self, folder: &mut F)
258                                               -> TraitAndProjections<'tcx> {
259         TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder))
260     }
261 }
262
263 impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
264     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
265         let TraitAndProjections(ref trait_ref, ref projection_bounds) = *self;
266         parameterized(f, trait_ref.substs,
267                       trait_ref.def_id,
268                       projection_bounds,
269                       |tcx| tcx.lookup_trait_def(trait_ref.def_id).generics.clone())
270     }
271 }
272
273 impl<'tcx> fmt::Display for ty::TraitTy<'tcx> {
274     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275         let bounds = &self.bounds;
276
277         // Generate the main trait ref, including associated types.
278         try!(ty::tls::with(|tcx| {
279             let principal = tcx.lift(&self.principal.0)
280                                .expect("could not lift TraitRef for printing");
281             let projections = tcx.lift(&bounds.projection_bounds[..])
282                                  .expect("could not lift projections for printing");
283             let projections = projections.into_iter().map(|p| p.0).collect();
284
285             let tap = ty::Binder(TraitAndProjections(principal, projections));
286             in_binder(f, tcx, &ty::Binder(""), Some(tap))
287         }));
288
289         // Builtin bounds.
290         for bound in &bounds.builtin_bounds {
291             try!(write!(f, " + {:?}", bound));
292         }
293
294         // FIXME: It'd be nice to compute from context when this bound
295         // is implied, but that's non-trivial -- we'd perhaps have to
296         // use thread-local data of some kind? There are also
297         // advantages to just showing the region, since it makes
298         // people aware that it's there.
299         let bound = bounds.region_bound.to_string();
300         if !bound.is_empty() {
301             try!(write!(f, " + {}", bound));
302         }
303
304         Ok(())
305     }
306 }
307
308 impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> {
309     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
310         write!(f, "TypeParameterDef({}, {}:{}, {:?}/{})",
311                self.name,
312                self.def_id.krate, self.def_id.node,
313                self.space, self.index)
314     }
315 }
316
317 impl fmt::Debug for ty::RegionParameterDef {
318     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319         write!(f, "RegionParameterDef({}, {}:{}, {:?}/{}, {:?})",
320                self.name,
321                self.def_id.krate, self.def_id.node,
322                self.space, self.index,
323                self.bounds)
324     }
325 }
326
327 impl<'tcx> fmt::Debug for ty::TyS<'tcx> {
328     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
329         write!(f, "{}", *self)
330     }
331 }
332
333 impl<'tcx> fmt::Display for ty::TypeAndMut<'tcx> {
334     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
335         write!(f, "{}{}",
336                if self.mutbl == ast::MutMutable { "mut " } else { "" },
337                self.ty)
338     }
339 }
340
341 impl<'tcx> fmt::Debug for subst::Substs<'tcx> {
342     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
343         write!(f, "Substs[types={:?}, regions={:?}]",
344                self.types, self.regions)
345     }
346 }
347
348 impl<'tcx> fmt::Debug for ty::ItemSubsts<'tcx> {
349     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
350         write!(f, "ItemSubsts({:?})", self.substs)
351     }
352 }
353
354 impl fmt::Debug for subst::RegionSubsts {
355     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
356         match *self {
357             subst::ErasedRegions => write!(f, "erased"),
358             subst::NonerasedRegions(ref regions) => write!(f, "{:?}", regions)
359         }
360     }
361 }
362
363 impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
364     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
365         // when printing out the debug representation, we don't need
366         // to enumerate the `for<...>` etc because the debruijn index
367         // tells you everything you need to know.
368         match self.substs.self_ty() {
369             None => write!(f, "{}", *self),
370             Some(self_ty) => write!(f, "<{:?} as {}>", self_ty, *self)
371         }
372     }
373 }
374
375 impl<'tcx> fmt::Debug for ty::TraitDef<'tcx> {
376     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
377         write!(f, "TraitDef(generics={:?}, trait_ref={:?})",
378                self.generics, self.trait_ref)
379     }
380 }
381
382 impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> {
383     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
384         ty::tls::with(|tcx| {
385             write!(f, "{}", tcx.item_path_str(self.did))
386         })
387     }
388 }
389
390 impl fmt::Display for ty::BoundRegion {
391     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
392         if verbose() {
393             return write!(f, "{:?}", *self);
394         }
395
396         match *self {
397             BrNamed(_, name) => write!(f, "{}", name),
398             BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
399         }
400     }
401 }
402
403 impl fmt::Debug for ty::BoundRegion {
404     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
405         match *self {
406             BrAnon(n) => write!(f, "BrAnon({:?})", n),
407             BrFresh(n) => write!(f, "BrFresh({:?})", n),
408             BrNamed(did, name) => {
409                 write!(f, "BrNamed({}:{}, {:?})", did.krate, did.node, name)
410             }
411             BrEnv => "BrEnv".fmt(f),
412         }
413     }
414 }
415
416 impl fmt::Debug for ty::Region {
417     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418         match *self {
419             ty::ReEarlyBound(ref data) => {
420                 write!(f, "ReEarlyBound({}, {:?}, {}, {})",
421                        data.param_id,
422                        data.space,
423                        data.index,
424                        data.name)
425             }
426
427             ty::ReLateBound(binder_id, ref bound_region) => {
428                 write!(f, "ReLateBound({:?}, {:?})",
429                        binder_id,
430                        bound_region)
431             }
432
433             ty::ReFree(ref fr) => write!(f, "{:?}", fr),
434
435             ty::ReScope(id) => {
436                 write!(f, "ReScope({:?})", id)
437             }
438
439             ty::ReStatic => write!(f, "ReStatic"),
440
441             ty::ReVar(ref vid) => {
442                 write!(f, "{:?}", vid)
443             }
444
445             ty::ReSkolemized(id, ref bound_region) => {
446                 write!(f, "ReSkolemized({}, {:?})", id.index, bound_region)
447             }
448
449             ty::ReEmpty => write!(f, "ReEmpty")
450         }
451     }
452 }
453
454 impl fmt::Display for ty::Region {
455     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
456         if verbose() {
457             return write!(f, "{:?}", *self);
458         }
459
460         // These printouts are concise.  They do not contain all the information
461         // the user might want to diagnose an error, but there is basically no way
462         // to fit that into a short string.  Hence the recommendation to use
463         // `explain_region()` or `note_and_explain_region()`.
464         match *self {
465             ty::ReEarlyBound(ref data) => {
466                 write!(f, "{}", data.name)
467             }
468             ty::ReLateBound(_, br) |
469             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
470             ty::ReSkolemized(_, br) => {
471                 write!(f, "{}", br)
472             }
473             ty::ReScope(_) |
474             ty::ReVar(_) => Ok(()),
475             ty::ReStatic => write!(f, "'static"),
476             ty::ReEmpty => write!(f, "'<empty>"),
477         }
478     }
479 }
480
481 impl fmt::Debug for ty::FreeRegion {
482     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
483         write!(f, "ReFree({:?}, {:?})",
484                self.scope, self.bound_region)
485     }
486 }
487
488 impl fmt::Debug for ty::ItemVariances {
489     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
490         write!(f, "ItemVariances(types={:?}, regions={:?})",
491                self.types, self.regions)
492     }
493 }
494
495 impl<'tcx> fmt::Debug for ty::GenericPredicates<'tcx> {
496     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
497         write!(f, "GenericPredicates({:?})", self.predicates)
498     }
499 }
500
501 impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> {
502     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
503         write!(f, "InstantiatedPredicates({:?})",
504                self.predicates)
505     }
506 }
507
508 impl<'tcx> fmt::Debug for ty::ImplOrTraitItem<'tcx> {
509     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
510         try!(write!(f, "ImplOrTraitItem("));
511         try!(match *self {
512             ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i),
513             ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i),
514             ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i),
515         });
516         write!(f, ")")
517     }
518 }
519
520 impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
521     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
522         try!(write!(f, "fn"));
523         fn_sig(f, &self.inputs, self.variadic, self.output)
524     }
525 }
526
527 impl<'tcx> fmt::Debug for ty::ExistentialBounds<'tcx> {
528     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
529         let mut empty = true;
530         let mut maybe_continue = |f: &mut fmt::Formatter| {
531             if empty {
532                 empty = false;
533                 Ok(())
534             } else {
535                 write!(f, " + ")
536             }
537         };
538
539         let region_str = format!("{:?}", self.region_bound);
540         if !region_str.is_empty() {
541             try!(maybe_continue(f));
542             try!(write!(f, "{}", region_str));
543         }
544
545         for bound in &self.builtin_bounds {
546             try!(maybe_continue(f));
547             try!(write!(f, "{:?}", bound));
548         }
549
550         for projection_bound in &self.projection_bounds {
551             try!(maybe_continue(f));
552             try!(write!(f, "{:?}", projection_bound));
553         }
554
555         Ok(())
556     }
557 }
558
559 impl fmt::Display for ty::BuiltinBounds {
560     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
561         let mut bounds = self.iter();
562         if let Some(bound) = bounds.next() {
563             try!(write!(f, "{:?}", bound));
564             for bound in bounds {
565                 try!(write!(f, " + {:?}", bound));
566             }
567         }
568         Ok(())
569     }
570 }
571
572 // The generic impl doesn't work yet because projections are not
573 // normalized under HRTB.
574 /*impl<T> fmt::Display for ty::Binder<T>
575     where T: fmt::Display + for<'a> ty::Lift<'a>,
576           for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
577 {
578     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
579         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
580     }
581 }*/
582
583 impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> {
584     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
585         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
586     }
587 }
588
589 impl<'tcx> fmt::Display for ty::Binder<ty::TraitPredicate<'tcx>> {
590     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
591         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
592     }
593 }
594
595 impl<'tcx> fmt::Display for ty::Binder<ty::EquatePredicate<'tcx>> {
596     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
597         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
598     }
599 }
600
601 impl<'tcx> fmt::Display for ty::Binder<ty::ProjectionPredicate<'tcx>> {
602     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
603         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
604     }
605 }
606
607 impl<'tcx> fmt::Display for ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region>> {
608     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
609         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
610     }
611 }
612
613 impl fmt::Display for ty::Binder<ty::OutlivesPredicate<ty::Region, ty::Region>> {
614     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
615         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
616     }
617 }
618
619 impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
620     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
621         parameterized(f, self.substs, self.def_id, &[],
622                       |tcx| tcx.lookup_trait_def(self.def_id).generics.clone())
623     }
624 }
625
626 impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
627     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
628         match *self {
629             TyBool => write!(f, "bool"),
630             TyChar => write!(f, "char"),
631             TyInt(t) => write!(f, "{}", ast_util::int_ty_to_string(t, None)),
632             TyUint(t) => write!(f, "{}", ast_util::uint_ty_to_string(t, None)),
633             TyFloat(t) => write!(f, "{}", ast_util::float_ty_to_string(t)),
634             TyBox(typ) => write!(f, "Box<{}>",  typ),
635             TyRawPtr(ref tm) => {
636                 write!(f, "*{} {}", match tm.mutbl {
637                     ast::MutMutable => "mut",
638                     ast::MutImmutable => "const",
639                 },  tm.ty)
640             }
641             TyRef(r, ref tm) => {
642                 try!(write!(f, "&"));
643                 let s = r.to_string();
644                 try!(write!(f, "{}", s));
645                 if !s.is_empty() {
646                     try!(write!(f, " "));
647                 }
648                 write!(f, "{}", tm)
649             }
650             TyTuple(ref tys) => {
651                 try!(write!(f, "("));
652                 let mut tys = tys.iter();
653                 if let Some(&ty) = tys.next() {
654                     try!(write!(f, "{},", ty));
655                     if let Some(&ty) = tys.next() {
656                         try!(write!(f, " {}", ty));
657                         for &ty in tys {
658                             try!(write!(f, ", {}", ty));
659                         }
660                     }
661                 }
662                 write!(f, ")")
663             }
664             TyBareFn(opt_def_id, ref bare_fn) => {
665                 if bare_fn.unsafety == ast::Unsafety::Unsafe {
666                     try!(write!(f, "unsafe "));
667                 }
668
669                 if bare_fn.abi != abi::Rust {
670                     try!(write!(f, "extern {} ", bare_fn.abi));
671                 }
672
673                 try!(write!(f, "{}", bare_fn.sig.0));
674
675                 if let Some(def_id) = opt_def_id {
676                     try!(write!(f, " {{{}}}", ty::tls::with(|tcx| {
677                         tcx.item_path_str(def_id)
678                     })));
679                 }
680                 Ok(())
681             }
682             TyInfer(infer_ty) => write!(f, "{}", infer_ty),
683             TyError => write!(f, "[type error]"),
684             TyParam(ref param_ty) => write!(f, "{}", param_ty),
685             TyEnum(def, substs) | TyStruct(def, substs) => {
686                 ty::tls::with(|tcx| {
687                     if def.did.is_local() &&
688                           !tcx.tcache.borrow().contains_key(&def.did) {
689                         write!(f, "{}<..>", tcx.item_path_str(def.did))
690                     } else {
691                         parameterized(f, substs, def.did, &[],
692                                       |tcx| tcx.lookup_item_type(def.did).generics)
693                     }
694                 })
695             }
696             TyTrait(ref data) => write!(f, "{}", data),
697             ty::TyProjection(ref data) => write!(f, "{}", data),
698             TyStr => write!(f, "str"),
699             TyClosure(ref did, ref substs) => ty::tls::with(|tcx| {
700                 try!(write!(f, "[closure"));
701
702                 if did.is_local() {
703                     try!(write!(f, "@{:?}", tcx.map.span(did.node)));
704                     let mut sep = " ";
705                     try!(tcx.with_freevars(did.node, |freevars| {
706                         for (freevar, upvar_ty) in freevars.iter().zip(&substs.upvar_tys) {
707                             let node_id = freevar.def.local_node_id();
708                             try!(write!(f,
709                                         "{}{}:{}",
710                                         sep,
711                                         tcx.local_var_name_str(node_id),
712                                         upvar_ty));
713                             sep = ", ";
714                         }
715                         Ok(())
716                     }))
717                 } else {
718                     // cross-crate closure types should only be
719                     // visible in trans bug reports, I imagine.
720                     try!(write!(f, "@{:?}", did));
721                     let mut sep = " ";
722                     for (index, upvar_ty) in substs.upvar_tys.iter().enumerate() {
723                         try!(write!(f, "{}{}:{}", sep, index, upvar_ty));
724                         sep = ", ";
725                     }
726                 }
727
728                 write!(f, "]")
729             }),
730             TyArray(ty, sz) => write!(f, "[{}; {}]",  ty, sz),
731             TySlice(ty) => write!(f, "[{}]",  ty)
732         }
733     }
734 }
735
736 impl<'tcx> fmt::Display for ty::TyS<'tcx> {
737     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
738         write!(f, "{}", self.sty)
739     }
740 }
741
742 impl fmt::Debug for ty::UpvarId {
743     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
744         write!(f, "UpvarId({};`{}`;{})",
745                self.var_id,
746                ty::tls::with(|tcx| tcx.local_var_name_str(self.var_id)),
747                self.closure_expr_id)
748     }
749 }
750
751 impl fmt::Debug for ty::UpvarBorrow {
752     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
753         write!(f, "UpvarBorrow({:?}, {:?})",
754                self.kind, self.region)
755     }
756 }
757
758 impl fmt::Display for ty::InferTy {
759     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
760         let print_var_ids = verbose();
761         match *self {
762             ty::TyVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
763             ty::IntVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
764             ty::FloatVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
765             ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => write!(f, "_"),
766             ty::FreshTy(v) => write!(f, "FreshTy({})", v),
767             ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
768             ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
769         }
770     }
771 }
772
773 impl fmt::Display for ty::ExplicitSelfCategory {
774     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
775         f.write_str(match *self {
776             ty::StaticExplicitSelfCategory => "static",
777             ty::ByValueExplicitSelfCategory => "self",
778             ty::ByReferenceExplicitSelfCategory(_, ast::MutMutable) => {
779                 "&mut self"
780             }
781             ty::ByReferenceExplicitSelfCategory(_, ast::MutImmutable) => "&self",
782             ty::ByBoxExplicitSelfCategory => "Box<self>",
783         })
784     }
785 }
786
787 impl fmt::Display for ty::ParamTy {
788     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
789         write!(f, "{}", self.name)
790     }
791 }
792
793 impl fmt::Debug for ty::ParamTy {
794     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
795         write!(f, "{}/{:?}.{}", self, self.space, self.idx)
796     }
797 }
798
799 impl<'tcx, T, U> fmt::Display for ty::OutlivesPredicate<T,U>
800     where T: fmt::Display, U: fmt::Display
801 {
802     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
803         write!(f, "{} : {}", self.0, self.1)
804     }
805 }
806
807 impl<'tcx> fmt::Display for ty::EquatePredicate<'tcx> {
808     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
809         write!(f, "{} == {}", self.0, self.1)
810     }
811 }
812
813 impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
814     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
815         write!(f, "TraitPredicate({:?})",
816                self.trait_ref)
817     }
818 }
819
820 impl<'tcx> fmt::Display for ty::TraitPredicate<'tcx> {
821     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
822         write!(f, "{} : {}",
823                self.trait_ref.self_ty(),
824                self.trait_ref)
825     }
826 }
827
828 impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
829     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
830         write!(f, "ProjectionPredicate({:?}, {:?})",
831                self.projection_ty,
832                self.ty)
833     }
834 }
835
836 impl<'tcx> fmt::Display for ty::ProjectionPredicate<'tcx> {
837     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
838         write!(f, "{} == {}",
839                self.projection_ty,
840                self.ty)
841     }
842 }
843
844 impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> {
845     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
846         write!(f, "{:?}::{}",
847                self.trait_ref,
848                self.item_name)
849     }
850 }
851
852 impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
853     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
854         match *self {
855             ty::Predicate::Trait(ref data) => write!(f, "{}", data),
856             ty::Predicate::Equate(ref predicate) => write!(f, "{}", predicate),
857             ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
858             ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),
859             ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate),
860             ty::Predicate::WellFormed(ty) => write!(f, "{} well-formed", ty),
861             ty::Predicate::ObjectSafe(trait_def_id) =>
862                 ty::tls::with(|tcx| {
863                     write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
864                 }),
865         }
866     }
867 }