]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
Rollup merge of #44989 - QuietMisdreavus:what-is-your-quest, r=GuillaumeGomez
[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, 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                 TyProjection(ref data) => data.print(f, cx),
1016                 TyAnon(def_id, substs) => {
1017                     ty::tls::with(|tcx| {
1018                         // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1019                         // by looking up the projections associated with the def_id.
1020                         let predicates_of = tcx.predicates_of(def_id);
1021                         let substs = tcx.lift(&substs).unwrap_or_else(|| {
1022                             tcx.intern_substs(&[])
1023                         });
1024                         let bounds = predicates_of.instantiate(tcx, substs);
1025
1026                         let mut first = true;
1027                         let mut is_sized = false;
1028                         write!(f, "impl")?;
1029                         for predicate in bounds.predicates {
1030                             if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
1031                                 // Don't print +Sized, but rather +?Sized if absent.
1032                                 if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
1033                                     is_sized = true;
1034                                     continue;
1035                                 }
1036
1037                                 print!(f, cx,
1038                                        write("{}", if first { " " } else { "+" }),
1039                                        print(trait_ref))?;
1040                                 first = false;
1041                             }
1042                         }
1043                         if !is_sized {
1044                             write!(f, "{}?Sized", if first { " " } else { "+" })?;
1045                         }
1046                         Ok(())
1047                     })
1048                 }
1049                 TyStr => write!(f, "str"),
1050                 TyGenerator(did, substs, interior) => ty::tls::with(|tcx| {
1051                     let upvar_tys = substs.upvar_tys(did, tcx);
1052                     write!(f, "[generator")?;
1053
1054                     if let Some(node_id) = tcx.hir.as_local_node_id(did) {
1055                         write!(f, "@{:?}", tcx.hir.span(node_id))?;
1056                         let mut sep = " ";
1057                         tcx.with_freevars(node_id, |freevars| {
1058                             for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1059                                 print!(f, cx,
1060                                        write("{}{}:",
1061                                              sep,
1062                                              tcx.hir.name(freevar.var_id())),
1063                                        print(upvar_ty))?;
1064                                 sep = ", ";
1065                             }
1066                             Ok(())
1067                         })?
1068                     } else {
1069                         // cross-crate closure types should only be
1070                         // visible in trans bug reports, I imagine.
1071                         write!(f, "@{:?}", did)?;
1072                         let mut sep = " ";
1073                         for (index, upvar_ty) in upvar_tys.enumerate() {
1074                             print!(f, cx,
1075                                    write("{}{}:", sep, index),
1076                                    print(upvar_ty))?;
1077                             sep = ", ";
1078                         }
1079                     }
1080
1081                     print!(f, cx, write(" "), print(interior), write("]"))
1082                 }),
1083                 TyClosure(did, substs) => ty::tls::with(|tcx| {
1084                     let upvar_tys = substs.upvar_tys(did, tcx);
1085                     write!(f, "[closure")?;
1086
1087                     if let Some(node_id) = tcx.hir.as_local_node_id(did) {
1088                         if tcx.sess.opts.debugging_opts.span_free_formats {
1089                             write!(f, "@{:?}", node_id)?;
1090                         } else {
1091                             write!(f, "@{:?}", tcx.hir.span(node_id))?;
1092                         }
1093                         let mut sep = " ";
1094                         tcx.with_freevars(node_id, |freevars| {
1095                             for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1096                                 print!(f, cx,
1097                                        write("{}{}:",
1098                                              sep,
1099                                              tcx.hir.name(freevar.var_id())),
1100                                        print(upvar_ty))?;
1101                                 sep = ", ";
1102                             }
1103                             Ok(())
1104                         })?
1105                     } else {
1106                         // cross-crate closure types should only be
1107                         // visible in trans bug reports, I imagine.
1108                         write!(f, "@{:?}", did)?;
1109                         let mut sep = " ";
1110                         for (index, upvar_ty) in upvar_tys.enumerate() {
1111                             print!(f, cx,
1112                                    write("{}{}:", sep, index),
1113                                    print(upvar_ty))?;
1114                             sep = ", ";
1115                         }
1116                     }
1117
1118                     write!(f, "]")
1119                 }),
1120                 TyArray(ty, sz) => {
1121                     print!(f, cx, write("["), print(ty), write("; "))?;
1122                     match sz.val {
1123                         ConstVal::Integral(ConstInt::Usize(sz)) => {
1124                             write!(f, "{}", sz)?;
1125                         }
1126                         ConstVal::Unevaluated(_def_id, substs) => {
1127                             write!(f, "<unevaluated{:?}>", &substs[..])?;
1128                         }
1129                         _ => {
1130                             write!(f, "{:?}", sz)?;
1131                         }
1132                     }
1133                     write!(f, "]")
1134                 }
1135                 TySlice(ty) => {
1136                     print!(f, cx, write("["), print(ty), write("]"))
1137                 }
1138             }
1139         }
1140     }
1141 }
1142
1143 define_print! {
1144     ('tcx) ty::TyS<'tcx>, (self, f, cx) {
1145         display {
1146             self.sty.print(f, cx)
1147         }
1148         debug {
1149             self.sty.print_display(f, cx)
1150         }
1151     }
1152 }
1153
1154 define_print! {
1155     () ty::ParamTy, (self, f, cx) {
1156         display {
1157             write!(f, "{}", self.name)
1158         }
1159         debug {
1160             write!(f, "{}/#{}", self.name, self.idx)
1161         }
1162     }
1163 }
1164
1165 define_print! {
1166     ('tcx, T: Print + fmt::Debug, U: Print + fmt::Debug) ty::OutlivesPredicate<T, U>,
1167     (self, f, cx) {
1168         display {
1169             print!(f, cx, print(self.0), write(" : "), print(self.1))
1170         }
1171     }
1172 }
1173
1174 define_print! {
1175     ('tcx) ty::EquatePredicate<'tcx>, (self, f, cx) {
1176         display {
1177             print!(f, cx, print(self.0), write(" == "), print(self.1))
1178         }
1179     }
1180 }
1181
1182 define_print! {
1183     ('tcx) ty::SubtypePredicate<'tcx>, (self, f, cx) {
1184         display {
1185             print!(f, cx, print(self.a), write(" <: "), print(self.b))
1186         }
1187     }
1188 }
1189
1190 define_print! {
1191     ('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) {
1192         debug {
1193             write!(f, "TraitPredicate({:?})",
1194                    self.trait_ref)
1195         }
1196         display {
1197             print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1198         }
1199     }
1200 }
1201
1202 define_print! {
1203     ('tcx) ty::ProjectionPredicate<'tcx>, (self, f, cx) {
1204         debug {
1205             print!(f, cx,
1206                    write("ProjectionPredicate("),
1207                    print(self.projection_ty),
1208                    write(", "),
1209                    print(self.ty),
1210                    write(")"))
1211         }
1212         display {
1213             print!(f, cx, print(self.projection_ty), write(" == "), print(self.ty))
1214         }
1215     }
1216 }
1217
1218 define_print! {
1219     ('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) {
1220         display {
1221             // FIXME(tschottdorf): use something like
1222             //   parameterized(f, self.substs, self.item_def_id, &[])
1223             // (which currently ICEs).
1224             let (trait_ref, item_name) = ty::tls::with(|tcx|
1225                 (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).name)
1226             );
1227             print!(f, cx, print_debug(trait_ref), write("::{}", item_name))
1228         }
1229     }
1230 }
1231
1232 define_print! {
1233     () ty::ClosureKind, (self, f, cx) {
1234         display {
1235             match *self {
1236                 ty::ClosureKind::Fn => write!(f, "Fn"),
1237                 ty::ClosureKind::FnMut => write!(f, "FnMut"),
1238                 ty::ClosureKind::FnOnce => write!(f, "FnOnce"),
1239             }
1240         }
1241     }
1242 }
1243
1244 define_print! {
1245     ('tcx) ty::Predicate<'tcx>, (self, f, cx) {
1246         display {
1247             match *self {
1248                 ty::Predicate::Trait(ref data) => data.print(f, cx),
1249                 ty::Predicate::Equate(ref predicate) => predicate.print(f, cx),
1250                 ty::Predicate::Subtype(ref predicate) => predicate.print(f, cx),
1251                 ty::Predicate::RegionOutlives(ref predicate) => predicate.print(f, cx),
1252                 ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx),
1253                 ty::Predicate::Projection(ref predicate) => predicate.print(f, cx),
1254                 ty::Predicate::WellFormed(ty) => print!(f, cx, print(ty), write(" well-formed")),
1255                 ty::Predicate::ObjectSafe(trait_def_id) =>
1256                     ty::tls::with(|tcx| {
1257                         write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id))
1258                     }),
1259                 ty::Predicate::ClosureKind(closure_def_id, kind) =>
1260                     ty::tls::with(|tcx| {
1261                         write!(f, "the closure `{}` implements the trait `{}`",
1262                                tcx.item_path_str(closure_def_id), kind)
1263                     }),
1264                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1265                     write!(f, "the constant `")?;
1266                     cx.parameterized(f, substs, def_id, &[])?;
1267                     write!(f, "` can be evaluated")
1268                 }
1269             }
1270         }
1271         debug {
1272             match *self {
1273                 ty::Predicate::Trait(ref a) => a.print(f, cx),
1274                 ty::Predicate::Equate(ref pair) => pair.print(f, cx),
1275                 ty::Predicate::Subtype(ref pair) => pair.print(f, cx),
1276                 ty::Predicate::RegionOutlives(ref pair) => pair.print(f, cx),
1277                 ty::Predicate::TypeOutlives(ref pair) => pair.print(f, cx),
1278                 ty::Predicate::Projection(ref pair) => pair.print(f, cx),
1279                 ty::Predicate::WellFormed(ty) => ty.print(f, cx),
1280                 ty::Predicate::ObjectSafe(trait_def_id) => {
1281                     write!(f, "ObjectSafe({:?})", trait_def_id)
1282                 }
1283                 ty::Predicate::ClosureKind(closure_def_id, kind) => {
1284                     write!(f, "ClosureKind({:?}, {:?})", closure_def_id, kind)
1285                 }
1286                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1287                     write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
1288                 }
1289             }
1290         }
1291     }
1292 }