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