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