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