]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
a0939dc53dfcf23c3aaf301a56fc8cf59ce0084e
[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::{BrAnon, BrEnv, BrFresh, BrNamed};
15 use middle::ty::{TyBool, TyChar, TyStruct, TyEnum};
16 use middle::ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyBareFn};
17 use middle::ty::{TyParam, TyRawPtr, TyRef, TyTuple};
18 use middle::ty::TyClosure;
19 use middle::ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
20 use middle::ty::{self, Ty, TypeFoldable};
21
22 use std::fmt;
23 use syntax::abi::Abi;
24 use syntax::parse::token;
25 use syntax::ast::CRATE_NODE_ID;
26 use rustc_front::hir;
27
28 pub fn verbose() -> bool {
29     ty::tls::with(|tcx| tcx.sess.verbose())
30 }
31
32 fn fn_sig(f: &mut fmt::Formatter,
33           inputs: &[Ty],
34           variadic: bool,
35           output: ty::FnOutput)
36           -> fmt::Result {
37     try!(write!(f, "("));
38     let mut inputs = inputs.iter();
39     if let Some(&ty) = inputs.next() {
40         try!(write!(f, "{}", ty));
41         for &ty in inputs {
42             try!(write!(f, ", {}", ty));
43         }
44         if variadic {
45             try!(write!(f, ", ..."));
46         }
47     }
48     try!(write!(f, ")"));
49
50     match output {
51         ty::FnConverging(ty) => {
52             if !ty.is_nil() {
53                 try!(write!(f, " -> {}", ty));
54             }
55             Ok(())
56         }
57         ty::FnDiverging => {
58             write!(f, " -> !")
59         }
60     }
61 }
62
63 fn parameterized<GG>(f: &mut fmt::Formatter,
64                      substs: &subst::Substs,
65                      did: DefId,
66                      projections: &[ty::ProjectionPredicate],
67                      get_generics: GG)
68                      -> fmt::Result
69     where GG: for<'tcx> FnOnce(&ty::ctxt<'tcx>) -> ty::Generics<'tcx>
70 {
71     let (fn_trait_kind, verbose) = try!(ty::tls::with(|tcx| {
72         try!(write!(f, "{}", tcx.item_path_str(did)));
73         Ok((tcx.lang_items.fn_trait_kind(did), tcx.sess.verbose()))
74     }));
75
76     let mut empty = true;
77     let mut start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| {
78         if empty {
79             empty = false;
80             write!(f, "{}", start)
81         } else {
82             write!(f, "{}", cont)
83         }
84     };
85
86     if verbose {
87         match substs.regions {
88             subst::ErasedRegions => {
89                 try!(start_or_continue(f, "<", ", "));
90                 try!(write!(f, ".."));
91             }
92             subst::NonerasedRegions(ref regions) => {
93                 for region in regions {
94                     try!(start_or_continue(f, "<", ", "));
95                     try!(write!(f, "{:?}", region));
96                 }
97             }
98         }
99         for &ty in &substs.types {
100             try!(start_or_continue(f, "<", ", "));
101             try!(write!(f, "{}", ty));
102         }
103         for projection in projections {
104             try!(start_or_continue(f, "<", ", "));
105             try!(write!(f, "{}={}",
106                         projection.projection_ty.item_name,
107                         projection.ty));
108         }
109         return start_or_continue(f, "", ">");
110     }
111
112     if fn_trait_kind.is_some() && projections.len() == 1 {
113         let projection_ty = projections[0].ty;
114         if let TyTuple(ref args) = substs.types.get_slice(subst::TypeSpace)[0].sty {
115             return fn_sig(f, args, false, ty::FnConverging(projection_ty));
116         }
117     }
118
119     match substs.regions {
120         subst::ErasedRegions => { }
121         subst::NonerasedRegions(ref regions) => {
122             for &r in regions {
123                 try!(start_or_continue(f, "<", ", "));
124                 let s = r.to_string();
125                 if s.is_empty() {
126                     // This happens when the value of the region
127                     // parameter is not easily serialized. This may be
128                     // because the user omitted it in the first place,
129                     // or because it refers to some block in the code,
130                     // etc. I'm not sure how best to serialize this.
131                     try!(write!(f, "'_"));
132                 } else {
133                     try!(write!(f, "{}", s));
134                 }
135             }
136         }
137     }
138
139     // It is important to execute this conditionally, only if -Z
140     // verbose is false. Otherwise, debug logs can sometimes cause
141     // ICEs trying to fetch the generics early in the pipeline. This
142     // is kind of a hacky workaround in that -Z verbose is required to
143     // avoid those ICEs.
144     let tps = substs.types.get_slice(subst::TypeSpace);
145     let num_defaults = ty::tls::with(|tcx| {
146         let generics = get_generics(tcx);
147
148         let has_self = substs.self_ty().is_some();
149         let ty_params = generics.types.get_slice(subst::TypeSpace);
150         if ty_params.last().map_or(false, |def| def.default.is_some()) {
151             let substs = tcx.lift(&substs);
152             ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| {
153                 match def.default {
154                     Some(default) => {
155                         if !has_self && default.has_self_ty() {
156                             // In an object type, there is no `Self`, and
157                             // thus if the default value references Self,
158                             // the user will be required to give an
159                             // explicit value. We can't even do the
160                             // substitution below to check without causing
161                             // an ICE. (#18956).
162                             false
163                         } else {
164                             let default = tcx.lift(&default);
165                             substs.and_then(|substs| default.subst(tcx, substs)) == Some(actual)
166                         }
167                     }
168                     None => false
169                 }
170             }).count()
171         } else {
172             0
173         }
174     });
175
176     for &ty in &tps[..tps.len() - num_defaults] {
177         try!(start_or_continue(f, "<", ", "));
178         try!(write!(f, "{}", ty));
179     }
180
181     for projection in projections {
182         try!(start_or_continue(f, "<", ", "));
183         try!(write!(f, "{}={}",
184                     projection.projection_ty.item_name,
185                     projection.ty));
186     }
187
188     start_or_continue(f, "", ">")
189 }
190
191 fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter,
192                          tcx: &ty::ctxt<'tcx>,
193                          original: &ty::Binder<T>,
194                          lifted: Option<ty::Binder<U>>) -> fmt::Result
195     where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx>
196 {
197     // Replace any anonymous late-bound regions with named
198     // variants, using gensym'd identifiers, so that we can
199     // clearly differentiate between named and unnamed regions in
200     // the output. We'll probably want to tweak this over time to
201     // decide just how much information to give.
202     let value = if let Some(v) = lifted {
203         v
204     } else {
205         return write!(f, "{}", original.0);
206     };
207
208     let mut empty = true;
209     let mut start_or_continue = |f: &mut fmt::Formatter, start: &str, cont: &str| {
210         if empty {
211             empty = false;
212             write!(f, "{}", start)
213         } else {
214             write!(f, "{}", cont)
215         }
216     };
217
218     let new_value = tcx.replace_late_bound_regions(&value, |br| {
219         let _ = start_or_continue(f, "for<", ", ");
220         ty::ReLateBound(ty::DebruijnIndex::new(1), match br {
221             ty::BrNamed(_, name) => {
222                 let _ = write!(f, "{}", name);
223                 br
224             }
225             ty::BrAnon(_) |
226             ty::BrFresh(_) |
227             ty::BrEnv => {
228                 let name = token::intern("'r");
229                 let _ = write!(f, "{}", name);
230                 ty::BrNamed(tcx.map.local_def_id(CRATE_NODE_ID), name)
231             }
232         })
233     }).0;
234
235     try!(start_or_continue(f, "", "> "));
236     write!(f, "{}", new_value)
237 }
238
239 /// This curious type is here to help pretty-print trait objects. In
240 /// a trait object, the projections are stored separately from the
241 /// main trait bound, but in fact we want to package them together
242 /// when printing out; they also have separate binders, but we want
243 /// them to share a binder when we print them out. (And the binder
244 /// pretty-printing logic is kind of clever and we don't want to
245 /// reproduce it.) So we just repackage up the structure somewhat.
246 ///
247 /// Right now there is only one trait in an object that can have
248 /// projection bounds, so we just stuff them altogether. But in
249 /// reality we should eventually sort things out better.
250 #[derive(Clone, Debug)]
251 struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec<ty::ProjectionPredicate<'tcx>>);
252
253 impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
254     fn super_fold_with<F:ty::fold::TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
255         TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder))
256     }
257
258     fn super_visit_with<V: ty::fold::TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
259         self.0.visit_with(visitor) || self.1.visit_with(visitor)
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,
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,
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 == hir::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<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
391     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
392         match *self {
393             ty::adjustment::AdjustReifyFnPointer => {
394                 write!(f, "AdjustReifyFnPointer")
395             }
396             ty::adjustment::AdjustUnsafeFnPointer => {
397                 write!(f, "AdjustUnsafeFnPointer")
398             }
399             ty::adjustment::AdjustDerefRef(ref data) => {
400                 write!(f, "{:?}", data)
401             }
402         }
403     }
404 }
405
406 impl<'tcx> fmt::Debug for ty::adjustment::AutoDerefRef<'tcx> {
407     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
408         write!(f, "AutoDerefRef({}, unsize={:?}, {:?})",
409                self.autoderefs, self.unsize, self.autoref)
410     }
411 }
412
413 impl<'tcx> fmt::Debug for ty::TraitTy<'tcx> {
414     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
415         write!(f, "TraitTy({:?},{:?})",
416                self.principal,
417                self.bounds)
418     }
419 }
420
421 impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
422     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
423         match *self {
424             ty::Predicate::Trait(ref a) => write!(f, "{:?}", a),
425             ty::Predicate::Equate(ref pair) => write!(f, "{:?}", pair),
426             ty::Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair),
427             ty::Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair),
428             ty::Predicate::Projection(ref pair) => write!(f, "{:?}", pair),
429             ty::Predicate::WellFormed(ty) => write!(f, "WF({:?})", ty),
430             ty::Predicate::ObjectSafe(trait_def_id) => {
431                 write!(f, "ObjectSafe({:?})", trait_def_id)
432             }
433         }
434     }
435 }
436
437 impl fmt::Display for ty::BoundRegion {
438     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
439         if verbose() {
440             return write!(f, "{:?}", *self);
441         }
442
443         match *self {
444             BrNamed(_, name) => write!(f, "{}", name),
445             BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
446         }
447     }
448 }
449
450 impl fmt::Debug for ty::BoundRegion {
451     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
452         match *self {
453             BrAnon(n) => write!(f, "BrAnon({:?})", n),
454             BrFresh(n) => write!(f, "BrFresh({:?})", n),
455             BrNamed(did, name) => {
456                 write!(f, "BrNamed({:?}, {:?})", did, name)
457             }
458             BrEnv => "BrEnv".fmt(f),
459         }
460     }
461 }
462
463 impl fmt::Debug for ty::Region {
464     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
465         match *self {
466             ty::ReEarlyBound(ref data) => {
467                 write!(f, "ReEarlyBound({:?}, {}, {})",
468                        data.space,
469                        data.index,
470                        data.name)
471             }
472
473             ty::ReLateBound(binder_id, ref bound_region) => {
474                 write!(f, "ReLateBound({:?}, {:?})",
475                        binder_id,
476                        bound_region)
477             }
478
479             ty::ReFree(ref fr) => write!(f, "{:?}", fr),
480
481             ty::ReScope(id) => {
482                 write!(f, "ReScope({:?})", id)
483             }
484
485             ty::ReStatic => write!(f, "ReStatic"),
486
487             ty::ReVar(ref vid) => {
488                 write!(f, "{:?}", vid)
489             }
490
491             ty::ReSkolemized(id, ref bound_region) => {
492                 write!(f, "ReSkolemized({}, {:?})", id.index, bound_region)
493             }
494
495             ty::ReEmpty => write!(f, "ReEmpty")
496         }
497     }
498 }
499
500 impl<'tcx> fmt::Debug for ty::ClosureTy<'tcx> {
501     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
502         write!(f, "ClosureTy({},{:?},{})",
503                self.unsafety,
504                self.sig,
505                self.abi)
506     }
507 }
508
509 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
510     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
511         write!(f, "ClosureUpvar({:?},{:?})",
512                self.def,
513                self.ty)
514     }
515 }
516
517 impl<'a, 'tcx> fmt::Debug for ty::ParameterEnvironment<'a, 'tcx> {
518     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
519         write!(f, "ParameterEnvironment(\
520             free_substs={:?}, \
521             implicit_region_bound={:?}, \
522             caller_bounds={:?})",
523             self.free_substs,
524             self.implicit_region_bound,
525             self.caller_bounds)
526     }
527 }
528
529 impl<'tcx> fmt::Debug for ty::ObjectLifetimeDefault {
530     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
531         match *self {
532             ty::ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"),
533             ty::ObjectLifetimeDefault::BaseDefault => write!(f, "BaseDefault"),
534             ty::ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r),
535         }
536     }
537 }
538
539 impl fmt::Display for ty::Region {
540     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
541         if verbose() {
542             return write!(f, "{:?}", *self);
543         }
544
545         // These printouts are concise.  They do not contain all the information
546         // the user might want to diagnose an error, but there is basically no way
547         // to fit that into a short string.  Hence the recommendation to use
548         // `explain_region()` or `note_and_explain_region()`.
549         match *self {
550             ty::ReEarlyBound(ref data) => {
551                 write!(f, "{}", data.name)
552             }
553             ty::ReLateBound(_, br) |
554             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
555             ty::ReSkolemized(_, br) => {
556                 write!(f, "{}", br)
557             }
558             ty::ReScope(_) |
559             ty::ReVar(_) => Ok(()),
560             ty::ReStatic => write!(f, "'static"),
561             ty::ReEmpty => write!(f, "'<empty>"),
562         }
563     }
564 }
565
566 impl fmt::Debug for ty::FreeRegion {
567     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
568         write!(f, "ReFree({:?}, {:?})",
569                self.scope, self.bound_region)
570     }
571 }
572
573 impl fmt::Debug for ty::Variance {
574     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
575         f.write_str(match *self {
576             ty::Covariant => "+",
577             ty::Contravariant => "-",
578             ty::Invariant => "o",
579             ty::Bivariant => "*",
580         })
581     }
582 }
583
584 impl fmt::Debug for ty::ItemVariances {
585     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
586         write!(f, "ItemVariances(types={:?}, regions={:?})",
587                self.types, self.regions)
588     }
589 }
590
591 impl<'tcx> fmt::Debug for ty::GenericPredicates<'tcx> {
592     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
593         write!(f, "GenericPredicates({:?})", self.predicates)
594     }
595 }
596
597 impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> {
598     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
599         write!(f, "InstantiatedPredicates({:?})",
600                self.predicates)
601     }
602 }
603
604 impl<'tcx> fmt::Debug for ty::ImplOrTraitItem<'tcx> {
605     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
606         try!(write!(f, "ImplOrTraitItem("));
607         try!(match *self {
608             ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i),
609             ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i),
610             ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i),
611         });
612         write!(f, ")")
613     }
614 }
615
616 impl<'tcx> fmt::Display for ty::FnSig<'tcx> {
617     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
618         try!(write!(f, "fn"));
619         fn_sig(f, &self.inputs, self.variadic, self.output)
620     }
621 }
622
623 impl<'tcx> fmt::Debug for ty::ExistentialBounds<'tcx> {
624     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
625         let mut empty = true;
626         let mut maybe_continue = |f: &mut fmt::Formatter| {
627             if empty {
628                 empty = false;
629                 Ok(())
630             } else {
631                 write!(f, " + ")
632             }
633         };
634
635         let region_str = format!("{:?}", self.region_bound);
636         if !region_str.is_empty() {
637             try!(maybe_continue(f));
638             try!(write!(f, "{}", region_str));
639         }
640
641         for bound in &self.builtin_bounds {
642             try!(maybe_continue(f));
643             try!(write!(f, "{:?}", bound));
644         }
645
646         for projection_bound in &self.projection_bounds {
647             try!(maybe_continue(f));
648             try!(write!(f, "{:?}", projection_bound));
649         }
650
651         Ok(())
652     }
653 }
654
655 impl fmt::Display for ty::BuiltinBounds {
656     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
657         let mut bounds = self.iter();
658         if let Some(bound) = bounds.next() {
659             try!(write!(f, "{:?}", bound));
660             for bound in bounds {
661                 try!(write!(f, " + {:?}", bound));
662             }
663         }
664         Ok(())
665     }
666 }
667
668 impl fmt::Debug for ty::TyVid {
669     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
670         write!(f, "_#{}t", self.index)
671     }
672 }
673
674 impl fmt::Debug for ty::IntVid {
675     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
676         write!(f, "_#{}i", self.index)
677     }
678 }
679
680 impl fmt::Debug for ty::FloatVid {
681     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
682         write!(f, "_#{}f", self.index)
683     }
684 }
685
686 impl fmt::Debug for ty::RegionVid {
687     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
688         write!(f, "'_#{}r", self.index)
689     }
690 }
691
692 impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
693     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
694         write!(f, "({:?}; variadic: {})->{:?}", self.inputs, self.variadic, self.output)
695     }
696 }
697
698 impl fmt::Debug for ty::InferTy {
699     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
700         match *self {
701             ty::TyVar(ref v) => v.fmt(f),
702             ty::IntVar(ref v) => v.fmt(f),
703             ty::FloatVar(ref v) => v.fmt(f),
704             ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
705             ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
706             ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
707         }
708     }
709 }
710
711 impl fmt::Debug for ty::IntVarValue {
712     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
713         match *self {
714             ty::IntType(ref v) => v.fmt(f),
715             ty::UintType(ref v) => v.fmt(f),
716         }
717     }
718 }
719
720 // The generic impl doesn't work yet because projections are not
721 // normalized under HRTB.
722 /*impl<T> fmt::Display for ty::Binder<T>
723     where T: fmt::Display + for<'a> ty::Lift<'a>,
724           for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
725 {
726     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
727         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
728     }
729 }*/
730
731 impl<'tcx> fmt::Display for ty::Binder<ty::TraitRef<'tcx>> {
732     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
733         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
734     }
735 }
736
737 impl<'tcx> fmt::Display for ty::Binder<ty::TraitPredicate<'tcx>> {
738     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
739         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
740     }
741 }
742
743 impl<'tcx> fmt::Display for ty::Binder<ty::EquatePredicate<'tcx>> {
744     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
745         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
746     }
747 }
748
749 impl<'tcx> fmt::Display for ty::Binder<ty::ProjectionPredicate<'tcx>> {
750     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
751         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
752     }
753 }
754
755 impl<'tcx> fmt::Display for ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region>> {
756     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
757         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
758     }
759 }
760
761 impl fmt::Display for ty::Binder<ty::OutlivesPredicate<ty::Region, ty::Region>> {
762     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
763         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
764     }
765 }
766
767 impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
768     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
769         parameterized(f, self.substs, self.def_id, &[],
770                       |tcx| tcx.lookup_trait_def(self.def_id).generics.clone())
771     }
772 }
773
774 impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
775     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
776         match *self {
777             TyBool => write!(f, "bool"),
778             TyChar => write!(f, "char"),
779             TyInt(t) => write!(f, "{}", t.ty_to_string()),
780             TyUint(t) => write!(f, "{}", t.ty_to_string()),
781             TyFloat(t) => write!(f, "{}", t.ty_to_string()),
782             TyBox(typ) => write!(f, "Box<{}>",  typ),
783             TyRawPtr(ref tm) => {
784                 write!(f, "*{} {}", match tm.mutbl {
785                     hir::MutMutable => "mut",
786                     hir::MutImmutable => "const",
787                 },  tm.ty)
788             }
789             TyRef(r, ref tm) => {
790                 try!(write!(f, "&"));
791                 let s = r.to_string();
792                 try!(write!(f, "{}", s));
793                 if !s.is_empty() {
794                     try!(write!(f, " "));
795                 }
796                 write!(f, "{}", tm)
797             }
798             TyTuple(ref tys) => {
799                 try!(write!(f, "("));
800                 let mut tys = tys.iter();
801                 if let Some(&ty) = tys.next() {
802                     try!(write!(f, "{},", ty));
803                     if let Some(&ty) = tys.next() {
804                         try!(write!(f, " {}", ty));
805                         for &ty in tys {
806                             try!(write!(f, ", {}", ty));
807                         }
808                     }
809                 }
810                 write!(f, ")")
811             }
812             TyBareFn(opt_def_id, ref bare_fn) => {
813                 if bare_fn.unsafety == hir::Unsafety::Unsafe {
814                     try!(write!(f, "unsafe "));
815                 }
816
817                 if bare_fn.abi != Abi::Rust {
818                     try!(write!(f, "extern {} ", bare_fn.abi));
819                 }
820
821                 try!(write!(f, "{}", bare_fn.sig.0));
822
823                 if let Some(def_id) = opt_def_id {
824                     try!(write!(f, " {{{}}}", ty::tls::with(|tcx| {
825                         tcx.item_path_str(def_id)
826                     })));
827                 }
828                 Ok(())
829             }
830             TyInfer(infer_ty) => write!(f, "{}", infer_ty),
831             TyError => write!(f, "[type error]"),
832             TyParam(ref param_ty) => write!(f, "{}", param_ty),
833             TyEnum(def, substs) | TyStruct(def, substs) => {
834                 ty::tls::with(|tcx| {
835                     if def.did.is_local() &&
836                           !tcx.tcache.borrow().contains_key(&def.did) {
837                         write!(f, "{}<..>", tcx.item_path_str(def.did))
838                     } else {
839                         parameterized(f, substs, def.did, &[],
840                                       |tcx| tcx.lookup_item_type(def.did).generics)
841                     }
842                 })
843             }
844             TyTrait(ref data) => write!(f, "{}", data),
845             ty::TyProjection(ref data) => write!(f, "{}", data),
846             TyStr => write!(f, "str"),
847             TyClosure(did, ref substs) => ty::tls::with(|tcx| {
848                 try!(write!(f, "[closure"));
849
850                 if let Some(node_id) = tcx.map.as_local_node_id(did) {
851                     try!(write!(f, "@{:?}", tcx.map.span(node_id)));
852                     let mut sep = " ";
853                     try!(tcx.with_freevars(node_id, |freevars| {
854                         for (freevar, upvar_ty) in freevars.iter().zip(&substs.upvar_tys) {
855                             let node_id = freevar.def.var_id();
856                             try!(write!(f,
857                                         "{}{}:{}",
858                                         sep,
859                                         tcx.local_var_name_str(node_id),
860                                         upvar_ty));
861                             sep = ", ";
862                         }
863                         Ok(())
864                     }))
865                 } else {
866                     // cross-crate closure types should only be
867                     // visible in trans bug reports, I imagine.
868                     try!(write!(f, "@{:?}", did));
869                     let mut sep = " ";
870                     for (index, upvar_ty) in substs.upvar_tys.iter().enumerate() {
871                         try!(write!(f, "{}{}:{}", sep, index, upvar_ty));
872                         sep = ", ";
873                     }
874                 }
875
876                 write!(f, "]")
877             }),
878             TyArray(ty, sz) => write!(f, "[{}; {}]",  ty, sz),
879             TySlice(ty) => write!(f, "[{}]",  ty)
880         }
881     }
882 }
883
884 impl<'tcx> fmt::Display for ty::TyS<'tcx> {
885     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
886         write!(f, "{}", self.sty)
887     }
888 }
889
890 impl fmt::Debug for ty::UpvarId {
891     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
892         write!(f, "UpvarId({};`{}`;{})",
893                self.var_id,
894                ty::tls::with(|tcx| tcx.local_var_name_str(self.var_id)),
895                self.closure_expr_id)
896     }
897 }
898
899 impl fmt::Debug for ty::UpvarBorrow {
900     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
901         write!(f, "UpvarBorrow({:?}, {:?})",
902                self.kind, self.region)
903     }
904 }
905
906 impl fmt::Display for ty::InferTy {
907     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
908         let print_var_ids = verbose();
909         match *self {
910             ty::TyVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
911             ty::IntVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
912             ty::FloatVar(ref vid) if print_var_ids => write!(f, "{:?}", vid),
913             ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => write!(f, "_"),
914             ty::FreshTy(v) => write!(f, "FreshTy({})", v),
915             ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
916             ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
917         }
918     }
919 }
920
921 impl fmt::Display for ty::ExplicitSelfCategory {
922     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
923         f.write_str(match *self {
924             ty::ExplicitSelfCategory::Static => "static",
925             ty::ExplicitSelfCategory::ByValue => "self",
926             ty::ExplicitSelfCategory::ByReference(_, hir::MutMutable) => {
927                 "&mut self"
928             }
929             ty::ExplicitSelfCategory::ByReference(_, hir::MutImmutable) => "&self",
930             ty::ExplicitSelfCategory::ByBox => "Box<self>",
931         })
932     }
933 }
934
935 impl fmt::Display for ty::ParamTy {
936     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
937         write!(f, "{}", self.name)
938     }
939 }
940
941 impl fmt::Debug for ty::ParamTy {
942     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
943         write!(f, "{}/{:?}.{}", self, self.space, self.idx)
944     }
945 }
946
947 impl<'tcx, T, U> fmt::Display for ty::OutlivesPredicate<T,U>
948     where T: fmt::Display, U: fmt::Display
949 {
950     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
951         write!(f, "{} : {}", self.0, self.1)
952     }
953 }
954
955 impl<'tcx> fmt::Display for ty::EquatePredicate<'tcx> {
956     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
957         write!(f, "{} == {}", self.0, self.1)
958     }
959 }
960
961 impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
962     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
963         write!(f, "TraitPredicate({:?})",
964                self.trait_ref)
965     }
966 }
967
968 impl<'tcx> fmt::Display for ty::TraitPredicate<'tcx> {
969     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
970         write!(f, "{} : {}",
971                self.trait_ref.self_ty(),
972                self.trait_ref)
973     }
974 }
975
976 impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
977     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
978         write!(f, "ProjectionPredicate({:?}, {:?})",
979                self.projection_ty,
980                self.ty)
981     }
982 }
983
984 impl<'tcx> fmt::Display for ty::ProjectionPredicate<'tcx> {
985     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
986         write!(f, "{} == {}",
987                self.projection_ty,
988                self.ty)
989     }
990 }
991
992 impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> {
993     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
994         write!(f, "{:?}::{}",
995                self.trait_ref,
996                self.item_name)
997     }
998 }
999
1000 impl<'tcx> fmt::Display for ty::Predicate<'tcx> {
1001     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1002         match *self {
1003             ty::Predicate::Trait(ref data) => write!(f, "{}", data),
1004             ty::Predicate::Equate(ref predicate) => write!(f, "{}", predicate),
1005             ty::Predicate::RegionOutlives(ref predicate) => write!(f, "{}", predicate),
1006             ty::Predicate::TypeOutlives(ref predicate) => write!(f, "{}", predicate),
1007             ty::Predicate::Projection(ref predicate) => write!(f, "{}", predicate),
1008             ty::Predicate::WellFormed(ty) => write!(f, "{} well-formed", ty),
1009             ty::Predicate::ObjectSafe(trait_def_id) =>
1010                 ty::tls::with(|tcx| {
1011                     write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
1012                 }),
1013         }
1014     }
1015 }