]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
rustc: remove fields from ty::print::PrintConfig available from tcx.
[rust.git] / src / librustc / util / ppaux.rs
1 use crate::hir;
2 use crate::hir::def::Namespace;
3 use crate::hir::def_id::DefId;
4 use crate::ty::subst::{Kind, SubstsRef, UnpackedKind};
5 use crate::ty::{self, ParamConst, Ty};
6 use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer};
7 use crate::mir::interpret::ConstValue;
8
9 use std::fmt::{self, Write as _};
10 use std::iter;
11
12 use rustc_target::spec::abi::Abi;
13
14 macro_rules! gen_display_debug_body {
15     ( $with:path ) => {
16         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17             PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| {
18                 $with(&cx.tcx.lift(self).expect("could not lift for printing"), cx)?;
19                 Ok(())
20             })
21         }
22     };
23 }
24 macro_rules! gen_display_debug {
25     ( ($($x:tt)+) $target:ty, display yes ) => {
26         impl<$($x)+> fmt::Display for $target {
27             gen_display_debug_body! { Print::print_display }
28         }
29     };
30     ( () $target:ty, display yes ) => {
31         impl fmt::Display for $target {
32             gen_display_debug_body! { Print::print_display }
33         }
34     };
35     ( ($($x:tt)+) $target:ty, debug yes ) => {
36         impl<$($x)+> fmt::Debug for $target {
37             gen_display_debug_body! { Print::print_debug }
38         }
39     };
40     ( () $target:ty, debug yes ) => {
41         impl fmt::Debug for $target {
42             gen_display_debug_body! { Print::print_debug }
43         }
44     };
45     ( $generic:tt $target:ty, $t:ident no ) => {};
46 }
47 macro_rules! gen_print_impl {
48     ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
49         impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target {
50             type Output = P;
51             type Error = fmt::Error;
52             fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
53                 #[allow(unused_mut)]
54                 let mut $cx = $cx;
55                 let _: () = {
56                     define_scoped_cx!($cx);
57
58                     if $cx.config.is_debug $dbg
59                     else $disp
60                 };
61                 Ok($cx.printer)
62             }
63         }
64     };
65     ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
66         impl<P: PrettyPrinter> Print<'tcx, P> for $target {
67             type Output = P;
68             type Error = fmt::Error;
69             fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
70                 #[allow(unused_mut)]
71                 let mut $cx = $cx;
72                 let _: () = {
73                     define_scoped_cx!($cx);
74
75                     if $cx.config.is_debug $dbg
76                     else $disp
77                 };
78                 Ok($cx.printer)
79             }
80         }
81     };
82     ( $generic:tt $target:ty,
83       $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
84         gen_print_impl! { $generic $target, $vars $disp $dbg }
85         gen_display_debug! { $generic $target, display $gendisp }
86         gen_display_debug! { $generic $target, debug $gendbg }
87     }
88 }
89 macro_rules! define_print {
90     ( $generic:tt $target:ty,
91       $vars:tt { display $disp:block debug $dbg:block } ) => {
92         gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
93     };
94     ( $generic:tt $target:ty,
95       $vars:tt { debug $dbg:block display $disp:block } ) => {
96         gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
97     };
98     ( $generic:tt $target:ty,
99       $vars:tt { debug $dbg:block } ) => {
100         gen_print_impl! { $generic $target, $vars no {
101             bug!(concat!("display not implemented for ", stringify!($target)));
102         } yes $dbg }
103     };
104     ( $generic:tt $target:ty,
105       ($self:ident, $cx:ident) { display $disp:block } ) => {
106         gen_print_impl! { $generic $target, ($self, $cx) yes $disp no {
107             write!($cx.printer, "{:?}", $self)?
108         } }
109     };
110 }
111 macro_rules! define_print_multi {
112     ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
113         $(define_print! { $generic $target, $vars $def })*
114     };
115 }
116 macro_rules! nest {
117     ($closure:expr) => {
118         scoped_cx!() = scoped_cx!().nest($closure)?
119     }
120 }
121 macro_rules! print_inner {
122     (write ($($data:expr),+)) => {
123         write!(scoped_cx!().printer, $($data),+)?
124     };
125     ($kind:ident ($data:expr)) => {
126         nest!(|cx| $data.$kind(cx))
127     };
128 }
129 macro_rules! p {
130     ($($kind:ident $data:tt),+) => {
131         {
132             $(print_inner!($kind $data));+
133         }
134     };
135 }
136 macro_rules! define_scoped_cx {
137     ($cx:ident) => {
138         #[allow(unused_macros)]
139         macro_rules! scoped_cx {
140             () => ($cx)
141         }
142     };
143 }
144
145 pub fn parameterized<F: fmt::Write>(
146     f: &mut F,
147     did: DefId,
148     substs: SubstsRef<'_>,
149     ns: Namespace,
150 ) -> fmt::Result {
151     PrintCx::with_tls_tcx(FmtPrinter::new(f, ns), |cx| {
152         let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
153         cx.print_def_path(did, Some(substs), iter::empty())?;
154         Ok(())
155     })
156 }
157
158 define_print! {
159     ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, cx) {
160         display {
161             // Generate the main trait ref, including associated types.
162             let mut first = true;
163
164             if let Some(principal) = self.principal() {
165                 let mut resugared_principal = false;
166
167                 // Special-case `Fn(...) -> ...` and resugar it.
168                 let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id);
169                 if !cx.tcx.sess.verbose() && fn_trait_kind.is_some() {
170                     if let ty::Tuple(ref args) = principal.substs.type_at(0).sty {
171                         let mut projections = self.projection_bounds();
172                         if let (Some(proj), None) = (projections.next(), projections.next()) {
173                             nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty()));
174                             nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty));
175                             resugared_principal = true;
176                         }
177                     }
178                 }
179
180                 if !resugared_principal {
181                     // Use a type that can't appear in defaults of type parameters.
182                     let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
183                     let principal = principal.with_self_ty(cx.tcx, dummy_self);
184                     nest!(|cx| cx.print_def_path(
185                         principal.def_id,
186                         Some(principal.substs),
187                         self.projection_bounds(),
188                     ));
189                 }
190                 first = false;
191             }
192
193             // Builtin bounds.
194             // FIXME(eddyb) avoid printing twice (needed to ensure
195             // that the auto traits are sorted *and* printed via cx).
196             let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
197                 (cx.tcx.def_path_str(did), did)
198             }).collect();
199
200             // The auto traits come ordered by `DefPathHash`. While
201             // `DefPathHash` is *stable* in the sense that it depends on
202             // neither the host nor the phase of the moon, it depends
203             // "pseudorandomly" on the compiler version and the target.
204             //
205             // To avoid that causing instabilities in compiletest
206             // output, sort the auto-traits alphabetically.
207             auto_traits.sort();
208
209             for (_, def_id) in auto_traits {
210                 if !first {
211                     p!(write(" + "));
212                 }
213                 first = false;
214
215                 nest!(|cx| cx.print_def_path(def_id, None, iter::empty()));
216             }
217         }
218     }
219 }
220
221 impl fmt::Debug for ty::GenericParamDef {
222     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223         let type_name = match self.kind {
224             ty::GenericParamDefKind::Lifetime => "Lifetime",
225             ty::GenericParamDefKind::Type { .. } => "Type",
226             ty::GenericParamDefKind::Const => "Const",
227         };
228         write!(f, "{}({}, {:?}, {})",
229                type_name,
230                self.name,
231                self.def_id,
232                self.index)
233     }
234 }
235
236 impl fmt::Debug for ty::TraitDef {
237     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238         PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| {
239             cx.print_def_path(self.def_id, None, iter::empty())?;
240             Ok(())
241         })
242     }
243 }
244
245 impl fmt::Debug for ty::AdtDef {
246     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247         PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| {
248             cx.print_def_path(self.did, None, iter::empty())?;
249             Ok(())
250         })
251     }
252 }
253
254 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
255     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256         write!(f, "ClosureUpvar({:?},{:?})",
257                self.def,
258                self.ty)
259     }
260 }
261
262 impl fmt::Debug for ty::UpvarId {
263     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264         PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::ValueNS), |mut cx| {
265             define_scoped_cx!(cx);
266             p!(write("UpvarId({:?};`{}`;{:?})",
267                 self.var_path.hir_id,
268                 cx.tcx.hir().name_by_hir_id(self.var_path.hir_id),
269                 self.closure_expr_id));
270             Ok(())
271         })
272     }
273 }
274
275 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
276     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277         write!(f, "UpvarBorrow({:?}, {:?})",
278                self.kind, self.region)
279     }
280 }
281
282 define_print! {
283     ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, cx) {
284         display {
285             p!(write("{{"));
286             let mut tys = self.iter();
287             if let Some(&ty) = tys.next() {
288                 p!(print(ty));
289                 for &ty in tys {
290                     p!(write(", "), print(ty));
291                 }
292             }
293             p!(write("}}"))
294         }
295     }
296 }
297
298 define_print! {
299     ('tcx) ty::TypeAndMut<'tcx>, (self, cx) {
300         display {
301             p!(
302                    write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
303                    print(self.ty))
304         }
305     }
306 }
307
308 define_print! {
309     ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) {
310         display {
311             let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
312
313             let trait_ref = *ty::Binder::bind(*self)
314                 .with_self_ty(cx.tcx, dummy_self)
315                 .skip_binder();
316             p!(print_display(trait_ref))
317         }
318         debug {
319             p!(print_display(self))
320         }
321     }
322 }
323
324 define_print! {
325     ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) {
326         debug {
327             p!(write("{:?} -> ", self.kind), print(self.target))
328         }
329     }
330 }
331
332 impl fmt::Debug for ty::BoundRegion {
333     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334         match *self {
335             ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
336             ty::BrFresh(n) => write!(f, "BrFresh({:?})", n),
337             ty::BrNamed(did, name) => {
338                 write!(f, "BrNamed({:?}:{:?}, {})",
339                         did.krate, did.index, name)
340             }
341             ty::BrEnv => write!(f, "BrEnv"),
342         }
343     }
344 }
345
346 define_print! {
347     () ty::RegionKind, (self, cx) {
348         display {
349             return cx.print_region(self);
350         }
351         debug {
352             match *self {
353                 ty::ReEarlyBound(ref data) => {
354                     p!(write("ReEarlyBound({}, {})",
355                            data.index,
356                            data.name))
357                 }
358
359                 ty::ReClosureBound(ref vid) => {
360                     p!(write("ReClosureBound({:?})", vid))
361                 }
362
363                 ty::ReLateBound(binder_id, ref bound_region) => {
364                     p!(write("ReLateBound({:?}, {:?})", binder_id, bound_region))
365                 }
366
367                 ty::ReFree(ref fr) => p!(print_debug(fr)),
368
369                 ty::ReScope(id) => {
370                     p!(write("ReScope({:?})", id))
371                 }
372
373                 ty::ReStatic => p!(write("ReStatic")),
374
375                 ty::ReVar(ref vid) => {
376                     p!(write("{:?}", vid));
377                 }
378
379                 ty::RePlaceholder(placeholder) => {
380                     p!(write("RePlaceholder({:?})", placeholder))
381                 }
382
383                 ty::ReEmpty => p!(write("ReEmpty")),
384
385                 ty::ReErased => p!(write("ReErased"))
386             }
387         }
388     }
389 }
390
391 define_print! {
392     () ty::FreeRegion, (self, cx) {
393         debug {
394             p!(write("ReFree({:?}, {:?})", self.scope, self.bound_region))
395         }
396     }
397 }
398
399 define_print! {
400     () ty::Variance, (self, cx) {
401         debug {
402             cx.printer.write_str(match *self {
403                 ty::Covariant => "+",
404                 ty::Contravariant => "-",
405                 ty::Invariant => "o",
406                 ty::Bivariant => "*",
407             })?
408         }
409     }
410 }
411
412 define_print! {
413     ('tcx) ty::FnSig<'tcx>, (self, cx) {
414         display {
415             if self.unsafety == hir::Unsafety::Unsafe {
416                 p!(write("unsafe "));
417             }
418
419             if self.abi != Abi::Rust {
420                 p!(write("extern {} ", self.abi));
421             }
422
423             p!(write("fn"));
424             nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
425         }
426         debug {
427             p!(write("({:?}; c_variadic: {})->{:?}",
428                 self.inputs(), self.c_variadic, self.output()))
429         }
430     }
431 }
432
433 impl fmt::Debug for ty::TyVid {
434     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
435         write!(f, "_#{}t", self.index)
436     }
437 }
438
439 impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
440     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441         write!(f, "_#{}f", self.index)
442     }
443 }
444
445 impl fmt::Debug for ty::IntVid {
446     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
447         write!(f, "_#{}i", self.index)
448     }
449 }
450
451 impl fmt::Debug for ty::FloatVid {
452     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
453         write!(f, "_#{}f", self.index)
454     }
455 }
456
457 impl fmt::Debug for ty::RegionVid {
458     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
459         write!(f, "'_#{}r", self.index())
460     }
461 }
462
463 define_print! {
464     () ty::InferTy, (self, cx) {
465         display {
466             if cx.tcx.sess.verbose() {
467                 return self.print_debug(cx);
468             }
469             match *self {
470                 ty::TyVar(_) => p!(write("_")),
471                 ty::IntVar(_) => p!(write("{}", "{integer}")),
472                 ty::FloatVar(_) => p!(write("{}", "{float}")),
473                 ty::FreshTy(v) => p!(write("FreshTy({})", v)),
474                 ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)),
475                 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v))
476             }
477         }
478         debug {
479             match *self {
480                 ty::TyVar(ref v) => p!(write("{:?}", v)),
481                 ty::IntVar(ref v) => p!(write("{:?}", v)),
482                 ty::FloatVar(ref v) => p!(write("{:?}", v)),
483                 ty::FreshTy(v) => p!(write("FreshTy({:?})", v)),
484                 ty::FreshIntTy(v) => p!(write("FreshIntTy({:?})", v)),
485                 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({:?})", v))
486             }
487         }
488     }
489 }
490
491 impl fmt::Debug for ty::IntVarValue {
492     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493         match *self {
494             ty::IntType(ref v) => v.fmt(f),
495             ty::UintType(ref v) => v.fmt(f),
496         }
497     }
498 }
499
500 impl fmt::Debug for ty::FloatVarValue {
501     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
502         self.0.fmt(f)
503     }
504 }
505
506 // The generic impl doesn't work yet because projections are not
507 // normalized under HRTB.
508 /*impl<T> fmt::Display for ty::Binder<T>
509     where T: fmt::Display + for<'a> ty::Lift<'a>,
510           for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
511 {
512     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513         PrintCx::with_tls_tcx(|cx| cx.pretty_in_binder(cx.tcx.lift(self)
514             .expect("could not lift for printing")))
515     }
516 }*/
517
518 define_print_multi! {
519     [
520     ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
521     ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
522     ('tcx) ty::Binder<ty::FnSig<'tcx>>,
523     ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
524     ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
525     ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
526     ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
527     ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
528     ]
529     (self, cx) {
530         display {
531             nest!(|cx| cx.pretty_in_binder(self))
532         }
533     }
534 }
535
536 define_print! {
537     ('tcx) ty::TraitRef<'tcx>, (self, cx) {
538         display {
539             nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty()));
540         }
541         debug {
542             nest!(|cx| cx.path_qualified(self.self_ty(), Some(*self)));
543         }
544     }
545 }
546
547 define_print! {
548     ('tcx) Ty<'tcx>, (self, cx) {
549         display {
550             return cx.print_type(self);
551         }
552         debug {
553             p!(print_display(self))
554         }
555     }
556 }
557
558 define_print! {
559     ('tcx) ConstValue<'tcx>, (self, cx) {
560         display {
561             match self {
562                 ConstValue::Infer(..) => p!(write("_")),
563                 ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
564                 _ => p!(write("{:?}", self)),
565             }
566         }
567     }
568 }
569
570 define_print! {
571     ('tcx) ty::Const<'tcx>, (self, cx) {
572         display {
573             p!(write("{} : {}", self.val, self.ty))
574         }
575     }
576 }
577
578 define_print! {
579     ('tcx) ty::LazyConst<'tcx>, (self, cx) {
580         display {
581             match self {
582                 // FIXME(const_generics) this should print at least the type.
583                 ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
584                 ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
585             }
586         }
587     }
588 }
589
590 define_print! {
591     () ty::ParamTy, (self, cx) {
592         display {
593             p!(write("{}", self.name))
594         }
595         debug {
596             p!(write("{}/#{}", self.name, self.idx))
597         }
598     }
599 }
600
601 define_print! {
602     () ty::ParamConst, (self, cx) {
603         display {
604             p!(write("{}", self.name))
605         }
606         debug {
607             p!(write("{}/#{}", self.name, self.index))
608         }
609     }
610 }
611
612 // Similar problem to `Binder<T>`, can't define a generic impl.
613 define_print_multi! {
614     [
615     ('tcx) ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
616     ('tcx) ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
617     ]
618     (self, cx) {
619         display {
620             p!(print(self.0), write(" : "), print(self.1))
621         }
622     }
623 }
624
625 define_print! {
626     ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) {
627         display {
628             p!(print(self.a), write(" <: "), print(self.b))
629         }
630     }
631 }
632
633 define_print! {
634     ('tcx) ty::TraitPredicate<'tcx>, (self, cx) {
635         debug {
636             p!(write("TraitPredicate({:?})",
637                    self.trait_ref))
638         }
639         display {
640             p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
641         }
642     }
643 }
644
645 define_print! {
646     ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) {
647         debug {
648             p!(
649                    write("ProjectionPredicate("),
650                    print(self.projection_ty),
651                    write(", "),
652                    print(self.ty),
653                    write(")"))
654         }
655         display {
656             p!(print(self.projection_ty), write(" == "), print(self.ty))
657         }
658     }
659 }
660
661 define_print! {
662     ('tcx) ty::ProjectionTy<'tcx>, (self, cx) {
663         display {
664             nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty()));
665         }
666     }
667 }
668
669 define_print! {
670     () ty::ClosureKind, (self, cx) {
671         display {
672             match *self {
673                 ty::ClosureKind::Fn => p!(write("Fn")),
674                 ty::ClosureKind::FnMut => p!(write("FnMut")),
675                 ty::ClosureKind::FnOnce => p!(write("FnOnce")),
676             }
677         }
678     }
679 }
680
681 define_print! {
682     ('tcx) ty::Predicate<'tcx>, (self, cx) {
683         display {
684             match *self {
685                 ty::Predicate::Trait(ref data) => p!(print(data)),
686                 ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
687                 ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
688                 ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
689                 ty::Predicate::Projection(ref predicate) => p!(print(predicate)),
690                 ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
691                 ty::Predicate::ObjectSafe(trait_def_id) => {
692                     p!(write("the trait `"));
693                     nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty()));
694                     p!(write("` is object-safe"))
695                 }
696                 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
697                     p!(write("the closure `"));
698                     nest!(|cx| cx.print_value_path(closure_def_id, None));
699                     p!(write("` implements the trait `{}`", kind))
700                 }
701                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
702                     p!(write("the constant `"));
703                     nest!(|cx| cx.print_value_path(def_id, Some(substs)));
704                     p!(write("` can be evaluated"))
705                 }
706             }
707         }
708         debug {
709             match *self {
710                 ty::Predicate::Trait(ref a) => p!(print(a)),
711                 ty::Predicate::Subtype(ref pair) => p!(print(pair)),
712                 ty::Predicate::RegionOutlives(ref pair) => p!(print(pair)),
713                 ty::Predicate::TypeOutlives(ref pair) => p!(print(pair)),
714                 ty::Predicate::Projection(ref pair) => p!(print(pair)),
715                 ty::Predicate::WellFormed(ty) => p!(print(ty)),
716                 ty::Predicate::ObjectSafe(trait_def_id) => {
717                     p!(write("ObjectSafe({:?})", trait_def_id))
718                 }
719                 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
720                     p!(write("ClosureKind({:?}, {:?}, {:?})",
721                         closure_def_id, closure_substs, kind))
722                 }
723                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
724                     p!(write("ConstEvaluatable({:?}, {:?})", def_id, substs))
725                 }
726             }
727         }
728     }
729 }
730
731 define_print! {
732     ('tcx) Kind<'tcx>, (self, cx) {
733         display {
734             match self.unpack() {
735                 UnpackedKind::Lifetime(lt) => p!(print(lt)),
736                 UnpackedKind::Type(ty) => p!(print(ty)),
737                 UnpackedKind::Const(ct) => p!(print(ct)),
738             }
739         }
740         debug {
741             match self.unpack() {
742                 UnpackedKind::Lifetime(lt) => p!(print(lt)),
743                 UnpackedKind::Type(ty) => p!(print(ty)),
744                 UnpackedKind::Const(ct) => p!(print(ct)),
745             }
746         }
747     }
748 }