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