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