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