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