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