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