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