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