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