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