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