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