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