]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
Fix impl Trait Lifetime Handling
[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 use hir::def_id::DefId;
12 use hir::map::definitions::DefPathData;
13 use middle::const_val::ConstVal;
14 use middle::region::{self, BlockRemainder};
15 use ty::subst::{self, Subst};
16 use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
17 use ty::{TyBool, TyChar, TyAdt};
18 use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
19 use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
20 use ty::{TyClosure, TyGenerator, TyForeign, TyProjection, TyAnon};
21 use ty::{TyDynamic, TyInt, TyUint, TyInfer};
22 use ty::{self, Ty, TyCtxt, TypeFoldable};
23 use util::nodemap::FxHashSet;
24
25 use std::cell::Cell;
26 use std::fmt;
27 use std::usize;
28
29 use rustc_const_math::ConstInt;
30 use rustc_data_structures::indexed_vec::Idx;
31 use syntax::abi::Abi;
32 use syntax::ast::CRATE_NODE_ID;
33 use syntax::symbol::Symbol;
34 use hir;
35
36 macro_rules! gen_display_debug_body {
37     ( $with:path ) => {
38         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39             let mut cx = PrintContext::new();
40             $with(self, f, &mut cx)
41         }
42     };
43 }
44 macro_rules! gen_display_debug {
45     ( ($($x:tt)+) $target:ty, display yes ) => {
46         impl<$($x)+> fmt::Display for $target {
47             gen_display_debug_body! { Print::print_display }
48         }
49     };
50     ( () $target:ty, display yes ) => {
51         impl fmt::Display for $target {
52             gen_display_debug_body! { Print::print_display }
53         }
54     };
55     ( ($($x:tt)+) $target:ty, debug yes ) => {
56         impl<$($x)+> fmt::Debug for $target {
57             gen_display_debug_body! { Print::print_debug }
58         }
59     };
60     ( () $target:ty, debug yes ) => {
61         impl fmt::Debug for $target {
62             gen_display_debug_body! { Print::print_debug }
63         }
64     };
65     ( $generic:tt $target:ty, $t:ident no ) => {};
66 }
67 macro_rules! gen_print_impl {
68     ( ($($x:tt)+) $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => {
69         impl<$($x)+> Print for $target {
70             fn print<F: fmt::Write>(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result {
71                 if $cx.is_debug $dbg
72                 else $disp
73             }
74         }
75     };
76     ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => {
77         impl Print for $target {
78             fn print<F: fmt::Write>(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result {
79                 if $cx.is_debug $dbg
80                 else $disp
81             }
82         }
83     };
84     ( $generic:tt $target:ty,
85       $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
86         gen_print_impl! { $generic $target, $vars $disp $dbg }
87         gen_display_debug! { $generic $target, display $gendisp }
88         gen_display_debug! { $generic $target, debug $gendbg }
89     }
90 }
91 macro_rules! define_print {
92     ( $generic:tt $target:ty,
93       $vars:tt { display $disp:block debug $dbg:block } ) => {
94         gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
95     };
96     ( $generic:tt $target:ty,
97       $vars:tt { debug $dbg:block display $disp:block } ) => {
98         gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
99     };
100     ( $generic:tt $target:ty,
101       $vars:tt { debug $dbg:block } ) => {
102         gen_print_impl! { $generic $target, $vars no {
103             bug!(concat!("display not implemented for ", stringify!($target)));
104         } yes $dbg }
105     };
106     ( $generic:tt $target:ty,
107       ($self:ident, $f:ident, $cx:ident) { display $disp:block } ) => {
108         gen_print_impl! { $generic $target, ($self, $f, $cx) yes $disp no {
109             write!($f, "{:?}", $self)
110         } }
111     };
112 }
113 macro_rules! define_print_multi {
114     ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
115         $(define_print! { $generic $target, $vars $def })*
116     };
117 }
118 macro_rules! print_inner {
119     ( $f:expr, $cx:expr, write ($($data:expr),+) ) => {
120         write!($f, $($data),+)
121     };
122     ( $f:expr, $cx:expr, $kind:ident ($data:expr) ) => {
123         $data.$kind($f, $cx)
124     };
125 }
126 macro_rules! print {
127     ( $f:expr, $cx:expr $(, $kind:ident $data:tt)+ ) => {
128         Ok(())$(.and_then(|_| print_inner!($f, $cx, $kind $data)))+
129     };
130 }
131
132
133 struct LateBoundRegionNameCollector(FxHashSet<Symbol>);
134 impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector {
135     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
136         match *r {
137             ty::ReLateBound(_, ty::BrNamed(_, name)) => {
138                 self.0.insert(name);
139             },
140             _ => {},
141         }
142         r.super_visit_with(self)
143     }
144 }
145
146 #[derive(Debug)]
147 pub struct PrintContext {
148     is_debug: bool,
149     is_verbose: bool,
150     identify_regions: bool,
151     used_region_names: Option<FxHashSet<Symbol>>,
152     region_index: usize,
153     binder_depth: usize,
154 }
155 impl PrintContext {
156     fn new() -> Self {
157         ty::tls::with_opt(|tcx| {
158             let (is_verbose, identify_regions) = tcx.map(
159                 |tcx| (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions)
160             ).unwrap_or((false, false));
161             PrintContext {
162                 is_debug: false,
163                 is_verbose: is_verbose,
164                 identify_regions: identify_regions,
165                 used_region_names: None,
166                 region_index: 0,
167                 binder_depth: 0,
168             }
169         })
170     }
171     fn prepare_late_bound_region_info<'tcx, T>(&mut self, value: &ty::Binder<T>)
172     where T: TypeFoldable<'tcx>
173     {
174         let mut collector = LateBoundRegionNameCollector(FxHashSet());
175         value.visit_with(&mut collector);
176         self.used_region_names = Some(collector.0);
177         self.region_index = 0;
178     }
179 }
180
181 pub trait Print {
182     fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result;
183     fn print_to_string(&self, cx: &mut PrintContext) -> String {
184         let mut result = String::new();
185         let _ = self.print(&mut result, cx);
186         result
187     }
188     fn print_display<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
189         let old_debug = cx.is_debug;
190         cx.is_debug = false;
191         let result = self.print(f, cx);
192         cx.is_debug = old_debug;
193         result
194     }
195     fn print_display_to_string(&self, cx: &mut PrintContext) -> String {
196         let mut result = String::new();
197         let _ = self.print_display(&mut result, cx);
198         result
199     }
200     fn print_debug<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
201         let old_debug = cx.is_debug;
202         cx.is_debug = true;
203         let result = self.print(f, cx);
204         cx.is_debug = old_debug;
205         result
206     }
207     fn print_debug_to_string(&self, cx: &mut PrintContext) -> String {
208         let mut result = String::new();
209         let _ = self.print_debug(&mut result, cx);
210         result
211     }
212 }
213
214 impl PrintContext {
215     fn fn_sig<F: fmt::Write>(&mut self,
216                              f: &mut F,
217                              inputs: &[Ty],
218                              variadic: bool,
219                              output: Ty)
220                              -> fmt::Result {
221         write!(f, "(")?;
222         let mut inputs = inputs.iter();
223         if let Some(&ty) = inputs.next() {
224             print!(f, self, print_display(ty))?;
225             for &ty in inputs {
226                 print!(f, self, write(", "), print_display(ty))?;
227             }
228             if variadic {
229                 write!(f, ", ...")?;
230             }
231         }
232         write!(f, ")")?;
233         if !output.is_nil() {
234             print!(f, self, write(" -> "), print_display(output))?;
235         }
236
237         Ok(())
238     }
239
240     fn parameterized<F: fmt::Write>(&mut self,
241                                     f: &mut F,
242                                     substs: &subst::Substs,
243                                     mut did: DefId,
244                                     projections: &[ty::ProjectionPredicate])
245                                     -> fmt::Result {
246         let key = ty::tls::with(|tcx| tcx.def_key(did));
247         let mut item_name = if let Some(name) = key.disambiguated_data.data.get_opt_name() {
248             Some(name)
249         } else {
250             did.index = key.parent.unwrap_or_else(
251                 || bug!("finding type for {:?}, encountered def-id {:?} with no parent",
252                         did, did));
253             self.parameterized(f, substs, did, projections)?;
254             return write!(f, "::{}", key.disambiguated_data.data.as_interned_str());
255         };
256
257         let verbose = self.is_verbose;
258         let mut num_supplied_defaults = 0;
259         let mut has_self = false;
260         let mut num_regions = 0;
261         let mut num_types = 0;
262         let mut is_value_path = false;
263         let fn_trait_kind = ty::tls::with(|tcx| {
264             // Unfortunately, some kinds of items (e.g., closures) don't have
265             // generics. So walk back up the find the closest parent that DOES
266             // have them.
267             let mut item_def_id = did;
268             loop {
269                 let key = tcx.def_key(item_def_id);
270                 match key.disambiguated_data.data {
271                     DefPathData::TypeNs(_) => {
272                         break;
273                     }
274                     DefPathData::ValueNs(_) | DefPathData::EnumVariant(_) => {
275                         is_value_path = true;
276                         break;
277                     }
278                     _ => {
279                         // if we're making a symbol for something, there ought
280                         // to be a value or type-def or something in there
281                         // *somewhere*
282                         item_def_id.index = key.parent.unwrap_or_else(|| {
283                             bug!("finding type for {:?}, encountered def-id {:?} with no \
284                                  parent", did, item_def_id);
285                         });
286                     }
287                 }
288             }
289             let mut generics = tcx.generics_of(item_def_id);
290             let mut path_def_id = did;
291             has_self = generics.has_self;
292
293             let mut child_types = 0;
294             if let Some(def_id) = generics.parent {
295                 // Methods.
296                 assert!(is_value_path);
297                 child_types = generics.types.len();
298                 generics = tcx.generics_of(def_id);
299                 num_regions = generics.regions.len();
300                 num_types = generics.types.len();
301
302                 if has_self {
303                     print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
304                 }
305
306                 path_def_id = def_id;
307             } else {
308                 item_name = None;
309
310                 if is_value_path {
311                     // Functions.
312                     assert_eq!(has_self, false);
313                 } else {
314                     // Types and traits.
315                     num_regions = generics.regions.len();
316                     num_types = generics.types.len();
317                 }
318             }
319
320             if !verbose {
321                 if generics.types.last().map_or(false, |def| def.has_default) {
322                     if let Some(substs) = tcx.lift(&substs) {
323                         let tps = substs.types().rev().skip(child_types);
324                         for (def, actual) in generics.types.iter().rev().zip(tps) {
325                             if !def.has_default {
326                                 break;
327                             }
328                             if tcx.type_of(def.def_id).subst(tcx, substs) != actual {
329                                 break;
330                             }
331                             num_supplied_defaults += 1;
332                         }
333                     }
334                 }
335             }
336
337             print!(f, self, write("{}", tcx.item_path_str(path_def_id)))?;
338             Ok(tcx.lang_items().fn_trait_kind(path_def_id))
339         })?;
340
341         if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
342             let projection_ty = projections[0].ty;
343             if let TyTuple(ref args, _) = substs.type_at(1).sty {
344                 return self.fn_sig(f, args, false, projection_ty);
345             }
346         }
347
348         let empty = Cell::new(true);
349         let start_or_continue = |f: &mut F, start: &str, cont: &str| {
350             if empty.get() {
351                 empty.set(false);
352                 write!(f, "{}", start)
353             } else {
354                 write!(f, "{}", cont)
355             }
356         };
357
358         let print_regions = |f: &mut F, start: &str, skip, count| {
359             // Don't print any regions if they're all erased.
360             let regions = || substs.regions().skip(skip).take(count);
361             if regions().all(|r: ty::Region| *r == ty::ReErased) {
362                 return Ok(());
363             }
364
365             for region in regions() {
366                 let region: ty::Region = region;
367                 start_or_continue(f, start, ", ")?;
368                 if verbose {
369                     write!(f, "{:?}", region)?;
370                 } else {
371                     let s = region.to_string();
372                     if s.is_empty() {
373                         // This happens when the value of the region
374                         // parameter is not easily serialized. This may be
375                         // because the user omitted it in the first place,
376                         // or because it refers to some block in the code,
377                         // etc. I'm not sure how best to serialize this.
378                         write!(f, "'_")?;
379                     } else {
380                         write!(f, "{}", s)?;
381                     }
382                 }
383             }
384
385             Ok(())
386         };
387
388         print_regions(f, "<", 0, num_regions)?;
389
390         let tps = substs.types().take(num_types - num_supplied_defaults)
391                                 .skip(has_self as usize);
392
393         for ty in tps {
394             start_or_continue(f, "<", ", ")?;
395             ty.print_display(f, self)?;
396         }
397
398         for projection in projections {
399             start_or_continue(f, "<", ", ")?;
400             ty::tls::with(|tcx|
401                 print!(f, self,
402                        write("{}=",
403                              tcx.associated_item(projection.projection_ty.item_def_id).name),
404                        print_display(projection.ty))
405             )?;
406         }
407
408         start_or_continue(f, "", ">")?;
409
410         // For values, also print their name and type parameters.
411         if is_value_path {
412             empty.set(true);
413
414             if has_self {
415                 write!(f, ">")?;
416             }
417
418             if let Some(item_name) = item_name {
419                 write!(f, "::{}", item_name)?;
420             }
421
422             print_regions(f, "::<", num_regions, usize::MAX)?;
423
424             // FIXME: consider being smart with defaults here too
425             for ty in substs.types().skip(num_types) {
426                 start_or_continue(f, "::<", ", ")?;
427                 ty.print_display(f, self)?;
428             }
429
430             start_or_continue(f, "", ">")?;
431         }
432
433         Ok(())
434     }
435
436     fn in_binder<'a, 'gcx, 'tcx, T, U, F>(&mut self,
437                                           f: &mut F,
438                                           tcx: TyCtxt<'a, 'gcx, 'tcx>,
439                                           original: &ty::Binder<T>,
440                                           lifted: Option<ty::Binder<U>>) -> fmt::Result
441         where T: Print, U: Print + TypeFoldable<'tcx>, F: fmt::Write
442     {
443         fn name_by_region_index(index: usize) -> Symbol {
444             match index {
445                 0 => Symbol::intern("'r"),
446                 1 => Symbol::intern("'s"),
447                 i => Symbol::intern(&format!("'t{}", i-2)),
448             }
449         }
450
451         // Replace any anonymous late-bound regions with named
452         // variants, using gensym'd identifiers, so that we can
453         // clearly differentiate between named and unnamed regions in
454         // the output. We'll probably want to tweak this over time to
455         // decide just how much information to give.
456         let value = if let Some(v) = lifted {
457             v
458         } else {
459             return original.0.print_display(f, self);
460         };
461
462         if self.binder_depth == 0 {
463             self.prepare_late_bound_region_info(&value);
464         }
465
466         let mut empty = true;
467         let mut start_or_continue = |f: &mut F, start: &str, cont: &str| {
468             if empty {
469                 empty = false;
470                 write!(f, "{}", start)
471             } else {
472                 write!(f, "{}", cont)
473             }
474         };
475
476         let old_region_index = self.region_index;
477         let mut region_index = old_region_index;
478         let new_value = tcx.replace_late_bound_regions(&value, |br| {
479             let _ = start_or_continue(f, "for<", ", ");
480             let br = match br {
481                 ty::BrNamed(_, name) => {
482                     let _ = write!(f, "{}", name);
483                     br
484                 }
485                 ty::BrAnon(_) |
486                 ty::BrFresh(_) |
487                 ty::BrEnv => {
488                     let name = loop {
489                         let name = name_by_region_index(region_index);
490                         region_index += 1;
491                         if !self.is_name_used(&name) {
492                             break name;
493                         }
494                     };
495                     let _ = write!(f, "{}", name);
496                     ty::BrNamed(tcx.hir.local_def_id(CRATE_NODE_ID),
497                                 name)
498                 }
499             };
500             tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), br))
501         }).0;
502         start_or_continue(f, "", "> ")?;
503
504         // Push current state to gcx, and restore after writing new_value.
505         self.binder_depth += 1;
506         self.region_index = region_index;
507         let result = new_value.print_display(f, self);
508         self.region_index = old_region_index;
509         self.binder_depth -= 1;
510         result
511     }
512
513     fn is_name_used(&self, name: &Symbol) -> bool {
514         match self.used_region_names {
515             Some(ref names) => names.contains(name),
516             None => false,
517         }
518     }
519 }
520
521 pub fn verbose() -> bool {
522     ty::tls::with(|tcx| tcx.sess.verbose())
523 }
524
525 pub fn identify_regions() -> bool {
526     ty::tls::with(|tcx| tcx.sess.opts.debugging_opts.identify_regions)
527 }
528
529 pub fn parameterized<F: fmt::Write>(f: &mut F,
530                                     substs: &subst::Substs,
531                                     did: DefId,
532                                     projections: &[ty::ProjectionPredicate])
533                                     -> fmt::Result {
534     PrintContext::new().parameterized(f, substs, did, projections)
535 }
536
537
538 impl<'a, T: Print> Print for &'a T {
539     fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result {
540         (*self).print(f, cx)
541     }
542 }
543
544 define_print! {
545     ('tcx) &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, (self, f, cx) {
546         display {
547             // Generate the main trait ref, including associated types.
548             ty::tls::with(|tcx| {
549                 // Use a type that can't appear in defaults of type parameters.
550                 let dummy_self = tcx.mk_infer(ty::FreshTy(0));
551
552                 if let Some(p) = self.principal() {
553                     let principal = tcx.lift(&p).expect("could not lift TraitRef for printing")
554                         .with_self_ty(tcx, dummy_self);
555                     let projections = self.projection_bounds().map(|p| {
556                         tcx.lift(&p)
557                             .expect("could not lift projection for printing")
558                             .with_self_ty(tcx, dummy_self)
559                     }).collect::<Vec<_>>();
560                     cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
561                 }
562
563                 // Builtin bounds.
564                 for did in self.auto_traits() {
565                     write!(f, " + {}", tcx.item_path_str(did))?;
566                 }
567
568                 Ok(())
569             })?;
570
571             Ok(())
572         }
573     }
574 }
575
576 impl fmt::Debug for ty::TypeParameterDef {
577     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
578         write!(f, "TypeParameterDef({}, {:?}, {})",
579                self.name,
580                self.def_id,
581                self.index)
582     }
583 }
584
585 impl fmt::Debug for ty::RegionParameterDef {
586     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
587         write!(f, "RegionParameterDef({}, {:?}, {})",
588                self.name,
589                self.def_id,
590                self.index)
591     }
592 }
593
594 impl fmt::Debug for ty::TraitDef {
595     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
596         ty::tls::with(|tcx| {
597             write!(f, "{}", tcx.item_path_str(self.def_id))
598         })
599     }
600 }
601
602 impl fmt::Debug for ty::AdtDef {
603     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
604         ty::tls::with(|tcx| {
605             write!(f, "{}", tcx.item_path_str(self.did))
606         })
607     }
608 }
609
610 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
611     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
612         write!(f, "ClosureUpvar({:?},{:?})",
613                self.def,
614                self.ty)
615     }
616 }
617
618 impl fmt::Debug for ty::UpvarId {
619     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
620         write!(f, "UpvarId({:?};`{}`;{:?})",
621                self.var_id,
622                ty::tls::with(|tcx| tcx.hir.name(tcx.hir.hir_to_node_id(self.var_id))),
623                self.closure_expr_id)
624     }
625 }
626
627 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
628     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
629         write!(f, "UpvarBorrow({:?}, {:?})",
630                self.kind, self.region)
631     }
632 }
633
634 define_print! {
635     ('tcx) ty::TypeAndMut<'tcx>, (self, f, cx) {
636         display {
637             print!(f, cx,
638                    write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
639                    print(self.ty))
640         }
641     }
642 }
643
644 define_print! {
645     ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) {
646         debug {
647             ty::tls::with(|tcx| {
648                 let dummy_self = tcx.mk_infer(ty::FreshTy(0));
649
650                 let trait_ref = tcx.lift(&ty::Binder(*self))
651                                    .expect("could not lift TraitRef for printing")
652                                    .with_self_ty(tcx, dummy_self).0;
653                 cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[])
654             })
655         }
656     }
657 }
658
659 define_print! {
660     ('tcx) ty::adjustment::Adjustment<'tcx>, (self, f, cx) {
661         debug {
662             print!(f, cx, write("{:?} -> ", self.kind), print(self.target))
663         }
664     }
665 }
666
667 define_print! {
668     () ty::BoundRegion, (self, f, cx) {
669         display {
670             if cx.is_verbose {
671                 return self.print_debug(f, cx);
672             }
673
674             match *self {
675                 BrNamed(_, name) => write!(f, "{}", name),
676                 BrAnon(_) | BrFresh(_) | BrEnv => Ok(())
677             }
678         }
679         debug {
680             return match *self {
681                 BrAnon(n) => write!(f, "BrAnon({:?})", n),
682                 BrFresh(n) => write!(f, "BrFresh({:?})", n),
683                 BrNamed(did, name) => {
684                     write!(f, "BrNamed({:?}:{:?}, {:?})",
685                            did.krate, did.index, name)
686                 }
687                 BrEnv => write!(f, "BrEnv"),
688             };
689         }
690     }
691 }
692
693 define_print! {
694     () ty::RegionKind, (self, f, cx) {
695         display {
696             if cx.is_verbose {
697                 return self.print_debug(f, cx);
698             }
699
700             // These printouts are concise.  They do not contain all the information
701             // the user might want to diagnose an error, but there is basically no way
702             // to fit that into a short string.  Hence the recommendation to use
703             // `explain_region()` or `note_and_explain_region()`.
704             match *self {
705                 ty::ReEarlyBound(ref data) => {
706                     write!(f, "{}", data.name)
707                 }
708                 ty::ReLateBound(_, br) |
709                 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
710                 ty::ReSkolemized(_, br) => {
711                     write!(f, "{}", br)
712                 }
713                 ty::ReScope(scope) if cx.identify_regions => {
714                     match scope.data() {
715                         region::ScopeData::Node(id) =>
716                             write!(f, "'{}s", id.as_usize()),
717                         region::ScopeData::CallSite(id) =>
718                             write!(f, "'{}cs", id.as_usize()),
719                         region::ScopeData::Arguments(id) =>
720                             write!(f, "'{}as", id.as_usize()),
721                         region::ScopeData::Destruction(id) =>
722                             write!(f, "'{}ds", id.as_usize()),
723                         region::ScopeData::Remainder(BlockRemainder
724                                                      { block, first_statement_index }) =>
725                             write!(f, "'{}_{}rs", block.as_usize(), first_statement_index.index()),
726                     }
727                 }
728                 ty::ReVar(region_vid) if cx.identify_regions => {
729                     write!(f, "'{}rv", region_vid.index)
730                 }
731                 ty::ReScope(_) |
732                 ty::ReVar(_) |
733                 ty::ReErased => Ok(()),
734                 ty::ReStatic => write!(f, "'static"),
735                 ty::ReEmpty => write!(f, "'<empty>"),
736             }
737         }
738         debug {
739             match *self {
740                 ty::ReEarlyBound(ref data) => {
741                     write!(f, "ReEarlyBound({}, {})",
742                            data.index,
743                            data.name)
744                 }
745
746                 ty::ReLateBound(binder_id, ref bound_region) => {
747                     write!(f, "ReLateBound({:?}, {:?})",
748                            binder_id,
749                            bound_region)
750                 }
751
752                 ty::ReFree(ref fr) => write!(f, "{:?}", fr),
753
754                 ty::ReScope(id) => {
755                     write!(f, "ReScope({:?})", id)
756                 }
757
758                 ty::ReStatic => write!(f, "ReStatic"),
759
760                 ty::ReVar(ref vid) => {
761                     write!(f, "{:?}", vid)
762                 }
763
764                 ty::ReSkolemized(id, ref bound_region) => {
765                     write!(f, "ReSkolemized({}, {:?})", id.index, bound_region)
766                 }
767
768                 ty::ReEmpty => write!(f, "ReEmpty"),
769
770                 ty::ReErased => write!(f, "ReErased")
771             }
772         }
773     }
774 }
775
776 define_print! {
777     () ty::FreeRegion, (self, f, cx) {
778         debug {
779             write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region)
780         }
781     }
782 }
783
784 define_print! {
785     () ty::Variance, (self, f, cx) {
786         debug {
787             f.write_str(match *self {
788                 ty::Covariant => "+",
789                 ty::Contravariant => "-",
790                 ty::Invariant => "o",
791                 ty::Bivariant => "*",
792             })
793         }
794     }
795 }
796
797 define_print! {
798     ('tcx) ty::GenericPredicates<'tcx>, (self, f, cx) {
799         debug {
800             write!(f, "GenericPredicates({:?})", self.predicates)
801         }
802     }
803 }
804
805 define_print! {
806     ('tcx) ty::InstantiatedPredicates<'tcx>, (self, f, cx) {
807         debug {
808             write!(f, "InstantiatedPredicates({:?})", self.predicates)
809         }
810     }
811 }
812
813 define_print! {
814     ('tcx) ty::FnSig<'tcx>, (self, f, cx) {
815         display {
816             if self.unsafety == hir::Unsafety::Unsafe {
817                 write!(f, "unsafe ")?;
818             }
819
820             if self.abi != Abi::Rust {
821                 write!(f, "extern {} ", self.abi)?;
822             }
823
824             write!(f, "fn")?;
825             cx.fn_sig(f, self.inputs(), self.variadic, self.output())
826         }
827         debug {
828             write!(f, "({:?}; variadic: {})->{:?}", self.inputs(), self.variadic, self.output())
829         }
830     }
831 }
832
833 impl fmt::Debug for ty::TyVid {
834     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
835         write!(f, "_#{}t", self.index)
836     }
837 }
838
839 impl fmt::Debug for ty::IntVid {
840     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
841         write!(f, "_#{}i", self.index)
842     }
843 }
844
845 impl fmt::Debug for ty::FloatVid {
846     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
847         write!(f, "_#{}f", self.index)
848     }
849 }
850
851 impl fmt::Debug for ty::RegionVid {
852     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
853         write!(f, "'_#{}r", self.index)
854     }
855 }
856
857 define_print! {
858     () ty::InferTy, (self, f, cx) {
859         display {
860             match *self {
861                 ty::TyVar(_) => write!(f, "_"),
862                 ty::IntVar(_) => write!(f, "{}", "{integer}"),
863                 ty::FloatVar(_) => write!(f, "{}", "{float}"),
864                 ty::FreshTy(v) => write!(f, "FreshTy({})", v),
865                 ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
866                 ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
867             }
868         }
869         debug {
870             match *self {
871                 ty::TyVar(ref v) => write!(f, "{:?}", v),
872                 ty::IntVar(ref v) => write!(f, "{:?}", v),
873                 ty::FloatVar(ref v) => write!(f, "{:?}", v),
874                 ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
875                 ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
876                 ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
877             }
878         }
879     }
880 }
881
882 impl fmt::Debug for ty::IntVarValue {
883     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
884         match *self {
885             ty::IntType(ref v) => v.fmt(f),
886             ty::UintType(ref v) => v.fmt(f),
887         }
888     }
889 }
890
891 // The generic impl doesn't work yet because projections are not
892 // normalized under HRTB.
893 /*impl<T> fmt::Display for ty::Binder<T>
894     where T: fmt::Display + for<'a> ty::Lift<'a>,
895           for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
896 {
897     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
898         ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self)))
899     }
900 }*/
901
902 define_print_multi! {
903     [
904     ('tcx) ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>,
905     ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
906     ('tcx) ty::Binder<ty::FnSig<'tcx>>,
907     ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
908     ('tcx) ty::Binder<ty::EquatePredicate<'tcx>>,
909     ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
910     ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
911     ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
912     ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
913     ]
914     (self, f, cx) {
915         display {
916             ty::tls::with(|tcx| cx.in_binder(f, tcx, self, tcx.lift(self)))
917         }
918     }
919 }
920
921 define_print! {
922     ('tcx) ty::TraitRef<'tcx>, (self, f, cx) {
923         display {
924             cx.parameterized(f, self.substs, self.def_id, &[])
925         }
926         debug {
927             // when printing out the debug representation, we don't need
928             // to enumerate the `for<...>` etc because the debruijn index
929             // tells you everything you need to know.
930             print!(f, cx,
931                    write("<"),
932                    print(self.self_ty()),
933                    write(" as "))?;
934             cx.parameterized(f, self.substs, self.def_id, &[])?;
935             write!(f, ">")
936         }
937     }
938 }
939
940 define_print! {
941     ('tcx) ty::GeneratorInterior<'tcx>, (self, f, cx) {
942         display {
943             self.witness.print(f, cx)
944         }
945     }
946 }
947
948 define_print! {
949     ('tcx) ty::TypeVariants<'tcx>, (self, f, cx) {
950         display {
951             match *self {
952                 TyBool => write!(f, "bool"),
953                 TyChar => write!(f, "char"),
954                 TyInt(t) => write!(f, "{}", t.ty_to_string()),
955                 TyUint(t) => write!(f, "{}", t.ty_to_string()),
956                 TyFloat(t) => write!(f, "{}", t.ty_to_string()),
957                 TyRawPtr(ref tm) => {
958                     write!(f, "*{} ", match tm.mutbl {
959                         hir::MutMutable => "mut",
960                         hir::MutImmutable => "const",
961                     })?;
962                     tm.ty.print(f, cx)
963                 }
964                 TyRef(r, ref tm) => {
965                     write!(f, "&")?;
966                     let s = r.print_to_string(cx);
967                     write!(f, "{}", s)?;
968                     if !s.is_empty() {
969                         write!(f, " ")?;
970                     }
971                     tm.print(f, cx)
972                 }
973                 TyNever => write!(f, "!"),
974                 TyTuple(ref tys, _) => {
975                     write!(f, "(")?;
976                     let mut tys = tys.iter();
977                     if let Some(&ty) = tys.next() {
978                         print!(f, cx, print(ty), write(","))?;
979                         if let Some(&ty) = tys.next() {
980                             print!(f, cx, write(" "), print(ty))?;
981                             for &ty in tys {
982                                 print!(f, cx, write(", "), print(ty))?;
983                             }
984                         }
985                     }
986                     write!(f, ")")
987                 }
988                 TyFnDef(def_id, substs) => {
989                     ty::tls::with(|tcx| {
990                         let mut sig = tcx.fn_sig(def_id);
991                         if let Some(substs) = tcx.lift(&substs) {
992                             sig = sig.subst(tcx, substs);
993                         }
994                         print!(f, cx, print(sig), write(" {{"))
995                     })?;
996                     cx.parameterized(f, substs, def_id, &[])?;
997                     write!(f, "}}")
998                 }
999                 TyFnPtr(ref bare_fn) => {
1000                     bare_fn.print(f, cx)
1001                 }
1002                 TyInfer(infer_ty) => write!(f, "{}", infer_ty),
1003                 TyError => write!(f, "[type error]"),
1004                 TyParam(ref param_ty) => write!(f, "{}", param_ty),
1005                 TyAdt(def, substs) => cx.parameterized(f, substs, def.did, &[]),
1006                 TyDynamic(data, r) => {
1007                     data.print(f, cx)?;
1008                     let r = r.print_to_string(cx);
1009                     if !r.is_empty() {
1010                         write!(f, " + {}", r)
1011                     } else {
1012                         Ok(())
1013                     }
1014                 }
1015                 TyForeign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]),
1016                 TyProjection(ref data) => data.print(f, cx),
1017                 TyAnon(def_id, substs) => {
1018                     if cx.is_verbose {
1019                         return write!(f, "TyAnon({:?}, {:?})", def_id, substs);
1020                     }
1021
1022                     ty::tls::with(|tcx| {
1023                         // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1024                         // by looking up the projections associated with the def_id.
1025                         let predicates_of = tcx.predicates_of(def_id);
1026                         let substs = tcx.lift(&substs).unwrap_or_else(|| {
1027                             tcx.intern_substs(&[])
1028                         });
1029                         let bounds = predicates_of.instantiate(tcx, substs);
1030
1031                         let mut first = true;
1032                         let mut is_sized = false;
1033                         write!(f, "impl")?;
1034                         for predicate in bounds.predicates {
1035                             if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
1036                                 // Don't print +Sized, but rather +?Sized if absent.
1037                                 if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
1038                                     is_sized = true;
1039                                     continue;
1040                                 }
1041
1042                                 print!(f, cx,
1043                                        write("{}", if first { " " } else { "+" }),
1044                                        print(trait_ref))?;
1045                                 first = false;
1046                             }
1047                         }
1048                         if !is_sized {
1049                             write!(f, "{}?Sized", if first { " " } else { "+" })?;
1050                         }
1051                         Ok(())
1052                     })
1053                 }
1054                 TyStr => write!(f, "str"),
1055                 TyGenerator(did, substs, interior) => ty::tls::with(|tcx| {
1056                     let upvar_tys = substs.upvar_tys(did, tcx);
1057                     write!(f, "[generator")?;
1058
1059                     if let Some(node_id) = tcx.hir.as_local_node_id(did) {
1060                         write!(f, "@{:?}", tcx.hir.span(node_id))?;
1061                         let mut sep = " ";
1062                         tcx.with_freevars(node_id, |freevars| {
1063                             for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1064                                 print!(f, cx,
1065                                        write("{}{}:",
1066                                              sep,
1067                                              tcx.hir.name(freevar.var_id())),
1068                                        print(upvar_ty))?;
1069                                 sep = ", ";
1070                             }
1071                             Ok(())
1072                         })?
1073                     } else {
1074                         // cross-crate closure types should only be
1075                         // visible in trans bug reports, I imagine.
1076                         write!(f, "@{:?}", did)?;
1077                         let mut sep = " ";
1078                         for (index, upvar_ty) in upvar_tys.enumerate() {
1079                             print!(f, cx,
1080                                    write("{}{}:", sep, index),
1081                                    print(upvar_ty))?;
1082                             sep = ", ";
1083                         }
1084                     }
1085
1086                     print!(f, cx, write(" "), print(interior), write("]"))
1087                 }),
1088                 TyClosure(did, substs) => ty::tls::with(|tcx| {
1089                     let upvar_tys = substs.upvar_tys(did, tcx);
1090                     write!(f, "[closure")?;
1091
1092                     if let Some(node_id) = tcx.hir.as_local_node_id(did) {
1093                         if tcx.sess.opts.debugging_opts.span_free_formats {
1094                             write!(f, "@{:?}", node_id)?;
1095                         } else {
1096                             write!(f, "@{:?}", tcx.hir.span(node_id))?;
1097                         }
1098                         let mut sep = " ";
1099                         tcx.with_freevars(node_id, |freevars| {
1100                             for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1101                                 print!(f, cx,
1102                                        write("{}{}:",
1103                                              sep,
1104                                              tcx.hir.name(freevar.var_id())),
1105                                        print(upvar_ty))?;
1106                                 sep = ", ";
1107                             }
1108                             Ok(())
1109                         })?
1110                     } else {
1111                         // cross-crate closure types should only be
1112                         // visible in trans bug reports, I imagine.
1113                         write!(f, "@{:?}", did)?;
1114                         let mut sep = " ";
1115                         for (index, upvar_ty) in upvar_tys.enumerate() {
1116                             print!(f, cx,
1117                                    write("{}{}:", sep, index),
1118                                    print(upvar_ty))?;
1119                             sep = ", ";
1120                         }
1121                     }
1122
1123                     write!(f, "]")
1124                 }),
1125                 TyArray(ty, sz) => {
1126                     print!(f, cx, write("["), print(ty), write("; "))?;
1127                     match sz.val {
1128                         ConstVal::Integral(ConstInt::Usize(sz)) => {
1129                             write!(f, "{}", sz)?;
1130                         }
1131                         ConstVal::Unevaluated(_def_id, substs) => {
1132                             write!(f, "<unevaluated{:?}>", &substs[..])?;
1133                         }
1134                         _ => {
1135                             write!(f, "{:?}", sz)?;
1136                         }
1137                     }
1138                     write!(f, "]")
1139                 }
1140                 TySlice(ty) => {
1141                     print!(f, cx, write("["), print(ty), write("]"))
1142                 }
1143             }
1144         }
1145     }
1146 }
1147
1148 define_print! {
1149     ('tcx) ty::TyS<'tcx>, (self, f, cx) {
1150         display {
1151             self.sty.print(f, cx)
1152         }
1153         debug {
1154             self.sty.print_display(f, cx)
1155         }
1156     }
1157 }
1158
1159 define_print! {
1160     () ty::ParamTy, (self, f, cx) {
1161         display {
1162             write!(f, "{}", self.name)
1163         }
1164         debug {
1165             write!(f, "{}/#{}", self.name, self.idx)
1166         }
1167     }
1168 }
1169
1170 define_print! {
1171     ('tcx, T: Print + fmt::Debug, U: Print + fmt::Debug) ty::OutlivesPredicate<T, U>,
1172     (self, f, cx) {
1173         display {
1174             print!(f, cx, print(self.0), write(" : "), print(self.1))
1175         }
1176     }
1177 }
1178
1179 define_print! {
1180     ('tcx) ty::EquatePredicate<'tcx>, (self, f, cx) {
1181         display {
1182             print!(f, cx, print(self.0), write(" == "), print(self.1))
1183         }
1184     }
1185 }
1186
1187 define_print! {
1188     ('tcx) ty::SubtypePredicate<'tcx>, (self, f, cx) {
1189         display {
1190             print!(f, cx, print(self.a), write(" <: "), print(self.b))
1191         }
1192     }
1193 }
1194
1195 define_print! {
1196     ('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) {
1197         debug {
1198             write!(f, "TraitPredicate({:?})",
1199                    self.trait_ref)
1200         }
1201         display {
1202             print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1203         }
1204     }
1205 }
1206
1207 define_print! {
1208     ('tcx) ty::ProjectionPredicate<'tcx>, (self, f, cx) {
1209         debug {
1210             print!(f, cx,
1211                    write("ProjectionPredicate("),
1212                    print(self.projection_ty),
1213                    write(", "),
1214                    print(self.ty),
1215                    write(")"))
1216         }
1217         display {
1218             print!(f, cx, print(self.projection_ty), write(" == "), print(self.ty))
1219         }
1220     }
1221 }
1222
1223 define_print! {
1224     ('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) {
1225         display {
1226             // FIXME(tschottdorf): use something like
1227             //   parameterized(f, self.substs, self.item_def_id, &[])
1228             // (which currently ICEs).
1229             let (trait_ref, item_name) = ty::tls::with(|tcx|
1230                 (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).name)
1231             );
1232             print!(f, cx, print_debug(trait_ref), write("::{}", item_name))
1233         }
1234     }
1235 }
1236
1237 define_print! {
1238     () ty::ClosureKind, (self, f, cx) {
1239         display {
1240             match *self {
1241                 ty::ClosureKind::Fn => write!(f, "Fn"),
1242                 ty::ClosureKind::FnMut => write!(f, "FnMut"),
1243                 ty::ClosureKind::FnOnce => write!(f, "FnOnce"),
1244             }
1245         }
1246     }
1247 }
1248
1249 define_print! {
1250     ('tcx) ty::Predicate<'tcx>, (self, f, cx) {
1251         display {
1252             match *self {
1253                 ty::Predicate::Trait(ref data) => data.print(f, cx),
1254                 ty::Predicate::Equate(ref predicate) => predicate.print(f, cx),
1255                 ty::Predicate::Subtype(ref predicate) => predicate.print(f, cx),
1256                 ty::Predicate::RegionOutlives(ref predicate) => predicate.print(f, cx),
1257                 ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx),
1258                 ty::Predicate::Projection(ref predicate) => predicate.print(f, cx),
1259                 ty::Predicate::WellFormed(ty) => print!(f, cx, print(ty), write(" well-formed")),
1260                 ty::Predicate::ObjectSafe(trait_def_id) =>
1261                     ty::tls::with(|tcx| {
1262                         write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
1263                     }),
1264                 ty::Predicate::ClosureKind(closure_def_id, kind) =>
1265                     ty::tls::with(|tcx| {
1266                         write!(f, "the closure `{}` implements the trait `{}`",
1267                                tcx.item_path_str(closure_def_id), kind)
1268                     }),
1269                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1270                     write!(f, "the constant `")?;
1271                     cx.parameterized(f, substs, def_id, &[])?;
1272                     write!(f, "` can be evaluated")
1273                 }
1274             }
1275         }
1276         debug {
1277             match *self {
1278                 ty::Predicate::Trait(ref a) => a.print(f, cx),
1279                 ty::Predicate::Equate(ref pair) => pair.print(f, cx),
1280                 ty::Predicate::Subtype(ref pair) => pair.print(f, cx),
1281                 ty::Predicate::RegionOutlives(ref pair) => pair.print(f, cx),
1282                 ty::Predicate::TypeOutlives(ref pair) => pair.print(f, cx),
1283                 ty::Predicate::Projection(ref pair) => pair.print(f, cx),
1284                 ty::Predicate::WellFormed(ty) => ty.print(f, cx),
1285                 ty::Predicate::ObjectSafe(trait_def_id) => {
1286                     write!(f, "ObjectSafe({:?})", trait_def_id)
1287                 }
1288                 ty::Predicate::ClosureKind(closure_def_id, kind) => {
1289                     write!(f, "ClosureKind({:?}, {:?})", closure_def_id, kind)
1290                 }
1291                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1292                     write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
1293                 }
1294             }
1295         }
1296     }
1297 }