]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
e14741f55ef194a32213e1bbb5400343be3b1290
[rust.git] / src / librustc / util / ppaux.rs
1 use crate::hir::def::Namespace;
2 use crate::hir::def_id::DefId;
3 use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind};
4 use crate::ty::{Bool, Char, Adt};
5 use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
6 use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
7 use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
8 use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
9 use crate::ty::{self, ParamConst, Ty, TypeFoldable};
10 use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer};
11 use crate::mir::interpret::ConstValue;
12
13 use std::fmt::{self, Write as _};
14 use std::iter;
15 use std::usize;
16
17 use rustc_target::spec::abi::Abi;
18 use syntax::ast::CRATE_NODE_ID;
19 use syntax::symbol::{Symbol, InternedString};
20 use crate::hir;
21
22 macro_rules! gen_display_debug_body {
23     ( $with:path ) => {
24         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25             PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| {
26                 $with(&cx.tcx.lift(self).expect("could not lift for printing"), cx)?;
27                 Ok(())
28             })
29         }
30     };
31 }
32 macro_rules! gen_display_debug {
33     ( ($($x:tt)+) $target:ty, display yes ) => {
34         impl<$($x)+> fmt::Display for $target {
35             gen_display_debug_body! { Print::print_display }
36         }
37     };
38     ( () $target:ty, display yes ) => {
39         impl fmt::Display for $target {
40             gen_display_debug_body! { Print::print_display }
41         }
42     };
43     ( ($($x:tt)+) $target:ty, debug yes ) => {
44         impl<$($x)+> fmt::Debug for $target {
45             gen_display_debug_body! { Print::print_debug }
46         }
47     };
48     ( () $target:ty, debug yes ) => {
49         impl fmt::Debug for $target {
50             gen_display_debug_body! { Print::print_debug }
51         }
52     };
53     ( $generic:tt $target:ty, $t:ident no ) => {};
54 }
55 macro_rules! gen_print_impl {
56     ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
57         impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target {
58             type Output = P;
59             type Error = fmt::Error;
60             fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
61                 #[allow(unused_mut)]
62                 let mut $cx = $cx;
63                 let _: () = {
64                     define_scoped_cx!($cx);
65
66                     if $cx.config.is_debug $dbg
67                     else $disp
68                 };
69                 Ok($cx.printer)
70             }
71         }
72     };
73     ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
74         impl<P: PrettyPrinter> Print<'tcx, P> for $target {
75             type Output = P;
76             type Error = fmt::Error;
77             fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
78                 #[allow(unused_mut)]
79                 let mut $cx = $cx;
80                 let _: () = {
81                     define_scoped_cx!($cx);
82
83                     if $cx.config.is_debug $dbg
84                     else $disp
85                 };
86                 Ok($cx.printer)
87             }
88         }
89     };
90     ( $generic:tt $target:ty,
91       $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
92         gen_print_impl! { $generic $target, $vars $disp $dbg }
93         gen_display_debug! { $generic $target, display $gendisp }
94         gen_display_debug! { $generic $target, debug $gendbg }
95     }
96 }
97 macro_rules! define_print {
98     ( $generic:tt $target:ty,
99       $vars:tt { display $disp:block debug $dbg:block } ) => {
100         gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
101     };
102     ( $generic:tt $target:ty,
103       $vars:tt { debug $dbg:block display $disp:block } ) => {
104         gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
105     };
106     ( $generic:tt $target:ty,
107       $vars:tt { debug $dbg:block } ) => {
108         gen_print_impl! { $generic $target, $vars no {
109             bug!(concat!("display not implemented for ", stringify!($target)));
110         } yes $dbg }
111     };
112     ( $generic:tt $target:ty,
113       ($self:ident, $cx:ident) { display $disp:block } ) => {
114         gen_print_impl! { $generic $target, ($self, $cx) yes $disp no {
115             write!($cx.printer, "{:?}", $self)?
116         } }
117     };
118 }
119 macro_rules! define_print_multi {
120     ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
121         $(define_print! { $generic $target, $vars $def })*
122     };
123 }
124 macro_rules! nest {
125     ($closure:expr) => {
126         scoped_cx!() = scoped_cx!().nest($closure)?
127     }
128 }
129 macro_rules! print_inner {
130     (write ($($data:expr),+)) => {
131         write!(scoped_cx!().printer, $($data),+)?
132     };
133     ($kind:ident ($data:expr)) => {
134         nest!(|cx| $data.$kind(cx))
135     };
136 }
137 macro_rules! p {
138     ($($kind:ident $data:tt),+) => {
139         {
140             $(print_inner!($kind $data));+
141         }
142     };
143 }
144 macro_rules! define_scoped_cx {
145     ($cx:ident) => {
146         #[allow(unused_macros)]
147         macro_rules! scoped_cx {
148             () => ($cx)
149         }
150     };
151 }
152
153 impl<P: PrettyPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
154     fn fn_sig(
155         mut self,
156         inputs: &[Ty<'tcx>],
157         c_variadic: bool,
158         output: Ty<'tcx>,
159     ) -> Result<P, fmt::Error> {
160         define_scoped_cx!(self);
161
162         p!(write("("));
163         let mut inputs = inputs.iter();
164         if let Some(&ty) = inputs.next() {
165             p!(print_display(ty));
166             for &ty in inputs {
167                 p!(write(", "), print_display(ty));
168             }
169             if c_variadic {
170                 p!(write(", ..."));
171             }
172         }
173         p!(write(")"));
174         if !output.is_unit() {
175             p!(write(" -> "), print_display(output));
176         }
177
178         Ok(self.printer)
179     }
180
181     fn in_binder<T>(mut self, value: &ty::Binder<T>) -> Result<P, fmt::Error>
182         where T: Print<'tcx, P, Output = P, Error = fmt::Error> + TypeFoldable<'tcx>
183     {
184         fn name_by_region_index(index: usize) -> InternedString {
185             match index {
186                 0 => Symbol::intern("'r"),
187                 1 => Symbol::intern("'s"),
188                 i => Symbol::intern(&format!("'t{}", i-2)),
189             }.as_interned_str()
190         }
191
192         // Replace any anonymous late-bound regions with named
193         // variants, using gensym'd identifiers, so that we can
194         // clearly differentiate between named and unnamed regions in
195         // the output. We'll probably want to tweak this over time to
196         // decide just how much information to give.
197         if self.config.binder_depth == 0 {
198             self.prepare_late_bound_region_info(value);
199         }
200
201         let mut empty = true;
202         let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
203             write!(cx.printer, "{}", if empty {
204                 empty = false;
205                 start
206             } else {
207                 cont
208             })
209         };
210
211         // NOTE(eddyb) this must be below `start_or_continue`'s definition
212         // as that also has a `define_scoped_cx` and that kind of shadowing
213         // is disallowed (name resolution thinks `scoped_cx!` is ambiguous).
214         define_scoped_cx!(self);
215
216         let old_region_index = self.config.region_index;
217         let mut region_index = old_region_index;
218         let new_value = self.tcx.replace_late_bound_regions(value, |br| {
219             let _ = start_or_continue(&mut self, "for<", ", ");
220             let br = match br {
221                 ty::BrNamed(_, name) => {
222                     let _ = write!(self.printer, "{}", name);
223                     br
224                 }
225                 ty::BrAnon(_) |
226                 ty::BrFresh(_) |
227                 ty::BrEnv => {
228                     let name = loop {
229                         let name = name_by_region_index(region_index);
230                         region_index += 1;
231                         if !self.is_name_used(&name) {
232                             break name;
233                         }
234                     };
235                     let _ = write!(self.printer, "{}", name);
236                     ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name)
237                 }
238             };
239             self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
240         }).0;
241         start_or_continue(&mut self, "", "> ")?;
242
243         // Push current state to gcx, and restore after writing new_value.
244         self.config.binder_depth += 1;
245         self.config.region_index = region_index;
246         let result = new_value.print_display(PrintCx {
247             tcx: self.tcx,
248             printer: self.printer,
249             config: self.config,
250         });
251         self.config.region_index = old_region_index;
252         self.config.binder_depth -= 1;
253         result
254     }
255
256     fn is_name_used(&self, name: &InternedString) -> bool {
257         match self.config.used_region_names {
258             Some(ref names) => names.contains(name),
259             None => false,
260         }
261     }
262 }
263
264 pub fn parameterized<F: fmt::Write>(
265     f: &mut F,
266     did: DefId,
267     substs: SubstsRef<'_>,
268     ns: Namespace,
269 ) -> fmt::Result {
270     PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| {
271         let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
272         cx.print_def_path(did, Some(substs), ns, iter::empty())?;
273         Ok(())
274     })
275 }
276
277 define_print! {
278     ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, cx) {
279         display {
280             // Generate the main trait ref, including associated types.
281             let mut first = true;
282
283             if let Some(principal) = self.principal() {
284                 let mut resugared_principal = false;
285
286                 // Special-case `Fn(...) -> ...` and resugar it.
287                 let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id);
288                 if !cx.config.is_verbose && fn_trait_kind.is_some() {
289                     if let ty::Tuple(ref args) = principal.substs.type_at(0).sty {
290                         let mut projections = self.projection_bounds();
291                         if let (Some(proj), None) = (projections.next(), projections.next()) {
292                             nest!(|cx| cx.print_def_path(
293                                 principal.def_id,
294                                 None,
295                                 Namespace::TypeNS,
296                                 iter::empty(),
297                             ));
298                             nest!(|cx| cx.fn_sig(args, false, proj.ty));
299                             resugared_principal = true;
300                         }
301                     }
302                 }
303
304                 if !resugared_principal {
305                     // Use a type that can't appear in defaults of type parameters.
306                     let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
307                     let principal = principal.with_self_ty(cx.tcx, dummy_self);
308                     nest!(|cx| cx.print_def_path(
309                         principal.def_id,
310                         Some(principal.substs),
311                         Namespace::TypeNS,
312                         self.projection_bounds(),
313                     ));
314                 }
315                 first = false;
316             }
317
318             // Builtin bounds.
319             // FIXME(eddyb) avoid printing twice (needed to ensure
320             // that the auto traits are sorted *and* printed via cx).
321             let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
322                 (cx.tcx.def_path_str(did), did)
323             }).collect();
324
325             // The auto traits come ordered by `DefPathHash`. While
326             // `DefPathHash` is *stable* in the sense that it depends on
327             // neither the host nor the phase of the moon, it depends
328             // "pseudorandomly" on the compiler version and the target.
329             //
330             // To avoid that causing instabilities in compiletest
331             // output, sort the auto-traits alphabetically.
332             auto_traits.sort();
333
334             for (_, def_id) in auto_traits {
335                 if !first {
336                     p!(write(" + "));
337                 }
338                 first = false;
339
340                 nest!(|cx| cx.print_def_path(
341                     def_id,
342                     None,
343                     Namespace::TypeNS,
344                     iter::empty(),
345                 ));
346             }
347         }
348     }
349 }
350
351 impl fmt::Debug for ty::GenericParamDef {
352     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353         let type_name = match self.kind {
354             ty::GenericParamDefKind::Lifetime => "Lifetime",
355             ty::GenericParamDefKind::Type { .. } => "Type",
356             ty::GenericParamDefKind::Const => "Const",
357         };
358         write!(f, "{}({}, {:?}, {})",
359                type_name,
360                self.name,
361                self.def_id,
362                self.index)
363     }
364 }
365
366 impl fmt::Debug for ty::TraitDef {
367     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
368         PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| {
369             cx.print_def_path(
370                 self.def_id,
371                 None,
372                 Namespace::TypeNS,
373                 iter::empty(),
374             )?;
375             Ok(())
376         })
377     }
378 }
379
380 impl fmt::Debug for ty::AdtDef {
381     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
382         PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| {
383             cx.print_def_path(
384                 self.did,
385                 None,
386                 Namespace::TypeNS,
387                 iter::empty(),
388             )?;
389             Ok(())
390         })
391     }
392 }
393
394 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
395     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396         write!(f, "ClosureUpvar({:?},{:?})",
397                self.def,
398                self.ty)
399     }
400 }
401
402 impl fmt::Debug for ty::UpvarId {
403     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404         PrintCx::with_tls_tcx(FmtPrinter::new(f), |mut cx| {
405             define_scoped_cx!(cx);
406             p!(write("UpvarId({:?};`{}`;{:?})",
407                 self.var_path.hir_id,
408                 cx.tcx.hir().name_by_hir_id(self.var_path.hir_id),
409                 self.closure_expr_id));
410             Ok(())
411         })
412     }
413 }
414
415 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
416     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417         write!(f, "UpvarBorrow({:?}, {:?})",
418                self.kind, self.region)
419     }
420 }
421
422 define_print! {
423     ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, cx) {
424         display {
425             p!(write("{{"));
426             let mut tys = self.iter();
427             if let Some(&ty) = tys.next() {
428                 p!(print(ty));
429                 for &ty in tys {
430                     p!(write(", "), print(ty));
431                 }
432             }
433             p!(write("}}"))
434         }
435     }
436 }
437
438 define_print! {
439     ('tcx) ty::TypeAndMut<'tcx>, (self, cx) {
440         display {
441             p!(
442                    write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
443                    print(self.ty))
444         }
445     }
446 }
447
448 define_print! {
449     ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) {
450         display {
451             let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
452
453             let trait_ref = *ty::Binder::bind(*self)
454                 .with_self_ty(cx.tcx, dummy_self)
455                 .skip_binder();
456             p!(print_display(trait_ref))
457         }
458         debug {
459             p!(print_display(self))
460         }
461     }
462 }
463
464 define_print! {
465     ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) {
466         debug {
467             p!(write("{:?} -> ", self.kind), print(self.target))
468         }
469     }
470 }
471
472 impl fmt::Debug for ty::BoundRegion {
473     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
474         match *self {
475             ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
476             ty::BrFresh(n) => write!(f, "BrFresh({:?})", n),
477             ty::BrNamed(did, name) => {
478                 write!(f, "BrNamed({:?}:{:?}, {})",
479                         did.krate, did.index, name)
480             }
481             ty::BrEnv => write!(f, "BrEnv"),
482         }
483     }
484 }
485
486 define_print! {
487     () ty::RegionKind, (self, cx) {
488         display {
489             return cx.print_region(self);
490         }
491         debug {
492             match *self {
493                 ty::ReEarlyBound(ref data) => {
494                     p!(write("ReEarlyBound({}, {})",
495                            data.index,
496                            data.name))
497                 }
498
499                 ty::ReClosureBound(ref vid) => {
500                     p!(write("ReClosureBound({:?})", vid))
501                 }
502
503                 ty::ReLateBound(binder_id, ref bound_region) => {
504                     p!(write("ReLateBound({:?}, {:?})", binder_id, bound_region))
505                 }
506
507                 ty::ReFree(ref fr) => p!(print_debug(fr)),
508
509                 ty::ReScope(id) => {
510                     p!(write("ReScope({:?})", id))
511                 }
512
513                 ty::ReStatic => p!(write("ReStatic")),
514
515                 ty::ReVar(ref vid) => {
516                     p!(write("{:?}", vid));
517                 }
518
519                 ty::RePlaceholder(placeholder) => {
520                     p!(write("RePlaceholder({:?})", placeholder))
521                 }
522
523                 ty::ReEmpty => p!(write("ReEmpty")),
524
525                 ty::ReErased => p!(write("ReErased"))
526             }
527         }
528     }
529 }
530
531 define_print! {
532     () ty::FreeRegion, (self, cx) {
533         debug {
534             p!(write("ReFree({:?}, {:?})", self.scope, self.bound_region))
535         }
536     }
537 }
538
539 define_print! {
540     () ty::Variance, (self, cx) {
541         debug {
542             cx.printer.write_str(match *self {
543                 ty::Covariant => "+",
544                 ty::Contravariant => "-",
545                 ty::Invariant => "o",
546                 ty::Bivariant => "*",
547             })?
548         }
549     }
550 }
551
552 define_print! {
553     ('tcx) ty::FnSig<'tcx>, (self, cx) {
554         display {
555             if self.unsafety == hir::Unsafety::Unsafe {
556                 p!(write("unsafe "));
557             }
558
559             if self.abi != Abi::Rust {
560                 p!(write("extern {} ", self.abi));
561             }
562
563             p!(write("fn"));
564             nest!(|cx| cx.fn_sig(self.inputs(), self.c_variadic, self.output()));
565         }
566         debug {
567             p!(write("({:?}; c_variadic: {})->{:?}",
568                 self.inputs(), self.c_variadic, self.output()))
569         }
570     }
571 }
572
573 impl fmt::Debug for ty::TyVid {
574     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575         write!(f, "_#{}t", self.index)
576     }
577 }
578
579 impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
580     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
581         write!(f, "_#{}f", self.index)
582     }
583 }
584
585 impl fmt::Debug for ty::IntVid {
586     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
587         write!(f, "_#{}i", self.index)
588     }
589 }
590
591 impl fmt::Debug for ty::FloatVid {
592     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
593         write!(f, "_#{}f", self.index)
594     }
595 }
596
597 impl fmt::Debug for ty::RegionVid {
598     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
599         write!(f, "'_#{}r", self.index())
600     }
601 }
602
603 define_print! {
604     () ty::InferTy, (self, cx) {
605         display {
606             if cx.config.is_verbose {
607                 return self.print_debug(cx);
608             }
609             match *self {
610                 ty::TyVar(_) => p!(write("_")),
611                 ty::IntVar(_) => p!(write("{}", "{integer}")),
612                 ty::FloatVar(_) => p!(write("{}", "{float}")),
613                 ty::FreshTy(v) => p!(write("FreshTy({})", v)),
614                 ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)),
615                 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v))
616             }
617         }
618         debug {
619             match *self {
620                 ty::TyVar(ref v) => p!(write("{:?}", v)),
621                 ty::IntVar(ref v) => p!(write("{:?}", v)),
622                 ty::FloatVar(ref v) => p!(write("{:?}", v)),
623                 ty::FreshTy(v) => p!(write("FreshTy({:?})", v)),
624                 ty::FreshIntTy(v) => p!(write("FreshIntTy({:?})", v)),
625                 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({:?})", v))
626             }
627         }
628     }
629 }
630
631 impl fmt::Debug for ty::IntVarValue {
632     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
633         match *self {
634             ty::IntType(ref v) => v.fmt(f),
635             ty::UintType(ref v) => v.fmt(f),
636         }
637     }
638 }
639
640 impl fmt::Debug for ty::FloatVarValue {
641     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
642         self.0.fmt(f)
643     }
644 }
645
646 // The generic impl doesn't work yet because projections are not
647 // normalized under HRTB.
648 /*impl<T> fmt::Display for ty::Binder<T>
649     where T: fmt::Display + for<'a> ty::Lift<'a>,
650           for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
651 {
652     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653         PrintCx::with_tls_tcx(|cx| cx.in_binder(cx.tcx.lift(self)
654             .expect("could not lift for printing")))
655     }
656 }*/
657
658 define_print_multi! {
659     [
660     ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
661     ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
662     ('tcx) ty::Binder<ty::FnSig<'tcx>>,
663     ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
664     ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
665     ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
666     ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
667     ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
668     ]
669     (self, cx) {
670         display {
671             nest!(|cx| cx.in_binder(self))
672         }
673     }
674 }
675
676 define_print! {
677     ('tcx) ty::TraitRef<'tcx>, (self, cx) {
678         display {
679             nest!(|cx| cx.print_def_path(
680                 self.def_id,
681                 Some(self.substs),
682                 Namespace::TypeNS,
683                 iter::empty(),
684             ));
685         }
686         debug {
687             nest!(|cx| cx.path_qualified(self.self_ty(), Some(*self), Namespace::TypeNS));
688         }
689     }
690 }
691
692 define_print! {
693     ('tcx) ty::Ty<'tcx>, (self, cx) {
694         display {
695             match self.sty {
696                 Bool => p!(write("bool")),
697                 Char => p!(write("char")),
698                 Int(t) => p!(write("{}", t.ty_to_string())),
699                 Uint(t) => p!(write("{}", t.ty_to_string())),
700                 Float(t) => p!(write("{}", t.ty_to_string())),
701                 RawPtr(ref tm) => {
702                     p!(write("*{} ", match tm.mutbl {
703                         hir::MutMutable => "mut",
704                         hir::MutImmutable => "const",
705                     }));
706                     p!(print(tm.ty))
707                 }
708                 Ref(r, ty, mutbl) => {
709                     p!(write("&"));
710                     if cx.print_region_outputs_anything(r) {
711                         p!(print_display(r), write(" "));
712                     }
713                     p!(print(ty::TypeAndMut { ty, mutbl }))
714                 }
715                 Never => p!(write("!")),
716                 Tuple(ref tys) => {
717                     p!(write("("));
718                     let mut tys = tys.iter();
719                     if let Some(&ty) = tys.next() {
720                         p!(print(ty), write(","));
721                         if let Some(&ty) = tys.next() {
722                             p!(write(" "), print(ty));
723                             for &ty in tys {
724                                 p!(write(", "), print(ty));
725                             }
726                         }
727                     }
728                     p!(write(")"))
729                 }
730                 FnDef(def_id, substs) => {
731                     let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs);
732                     p!(print(sig), write(" {{"));
733                     nest!(|cx| cx.print_def_path(
734                         def_id,
735                         Some(substs),
736                         Namespace::ValueNS,
737                         iter::empty(),
738                     ));
739                     p!(write("}}"))
740                 }
741                 FnPtr(ref bare_fn) => {
742                     p!(print(bare_fn))
743                 }
744                 Infer(infer_ty) => p!(write("{}", infer_ty)),
745                 Error => p!(write("[type error]")),
746                 Param(ref param_ty) => p!(write("{}", param_ty)),
747                 Bound(debruijn, bound_ty) => {
748                     match bound_ty.kind {
749                         ty::BoundTyKind::Anon => {
750                             if debruijn == ty::INNERMOST {
751                                 p!(write("^{}", bound_ty.var.index()))
752                             } else {
753                                 p!(write("^{}_{}", debruijn.index(), bound_ty.var.index()))
754                             }
755                         }
756
757                         ty::BoundTyKind::Param(p) => p!(write("{}", p)),
758                     }
759                 }
760                 Adt(def, substs) => {
761                     nest!(|cx| cx.print_def_path(
762                         def.did,
763                         Some(substs),
764                         Namespace::TypeNS,
765                         iter::empty(),
766                     ));
767                 }
768                 Dynamic(data, r) => {
769                     let print_r = cx.print_region_outputs_anything(r);
770                     if print_r {
771                         p!(write("("));
772                     }
773                     p!(write("dyn "), print(data));
774                     if print_r {
775                         p!(write(" + "), print_display(r), write(")"));
776                     }
777                 }
778                 Foreign(def_id) => {
779                     nest!(|cx| cx.print_def_path(
780                         def_id,
781                         None,
782                         Namespace::TypeNS,
783                         iter::empty(),
784                     ));
785                 }
786                 Projection(ref data) => p!(print(data)),
787                 UnnormalizedProjection(ref data) => {
788                     p!(write("Unnormalized("), print(data), write(")"))
789                 }
790                 Placeholder(placeholder) => {
791                     p!(write("Placeholder({:?})", placeholder))
792                 }
793                 Opaque(def_id, substs) => {
794                     if cx.config.is_verbose {
795                         p!(write("Opaque({:?}, {:?})", def_id, substs));
796                         return Ok(cx.printer);
797                     }
798
799                     let def_key = cx.tcx.def_key(def_id);
800                     if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
801                         p!(write("{}", name));
802                         let mut substs = substs.iter();
803                         // FIXME(eddyb) print this with `print_def_path`.
804                         if let Some(first) = substs.next() {
805                             p!(write("::<"));
806                             p!(print_display(first));
807                             for subst in substs {
808                                 p!(write(", "), print_display(subst));
809                             }
810                             p!(write(">"));
811                         }
812                         return Ok(cx.printer);
813                     }
814                     // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
815                     // by looking up the projections associated with the def_id.
816                     let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs);
817
818                     let mut first = true;
819                     let mut is_sized = false;
820                     p!(write("impl"));
821                     for predicate in bounds.predicates {
822                         if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
823                             // Don't print +Sized, but rather +?Sized if absent.
824                             if Some(trait_ref.def_id()) == cx.tcx.lang_items().sized_trait() {
825                                 is_sized = true;
826                                 continue;
827                             }
828
829                             p!(
830                                     write("{}", if first { " " } else { "+" }),
831                                     print(trait_ref));
832                             first = false;
833                         }
834                     }
835                     if !is_sized {
836                         p!(write("{}?Sized", if first { " " } else { "+" }));
837                     } else if first {
838                         p!(write(" Sized"));
839                     }
840                 }
841                 Str => p!(write("str")),
842                 Generator(did, substs, movability) => {
843                     let upvar_tys = substs.upvar_tys(did, cx.tcx);
844                     let witness = substs.witness(did, cx.tcx);
845                     if movability == hir::GeneratorMovability::Movable {
846                         p!(write("[generator"));
847                     } else {
848                         p!(write("[static generator"));
849                     }
850
851                     // FIXME(eddyb) should use `def_span`.
852                     if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
853                         p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)));
854                         let mut sep = " ";
855                         for (freevar, upvar_ty) in cx.tcx.freevars(did)
856                             .as_ref()
857                             .map_or(&[][..], |fv| &fv[..])
858                             .iter()
859                             .zip(upvar_tys)
860                         {
861                             p!(
862                                 write("{}{}:",
863                                         sep,
864                                         cx.tcx.hir().name(freevar.var_id())),
865                                 print(upvar_ty));
866                             sep = ", ";
867                         }
868                     } else {
869                         // cross-crate closure types should only be
870                         // visible in codegen bug reports, I imagine.
871                         p!(write("@{:?}", did));
872                         let mut sep = " ";
873                         for (index, upvar_ty) in upvar_tys.enumerate() {
874                             p!(
875                                    write("{}{}:", sep, index),
876                                    print(upvar_ty));
877                             sep = ", ";
878                         }
879                     }
880
881                     p!(write(" "), print(witness), write("]"))
882                 },
883                 GeneratorWitness(types) => {
884                     nest!(|cx| cx.in_binder(&types))
885                 }
886                 Closure(did, substs) => {
887                     let upvar_tys = substs.upvar_tys(did, cx.tcx);
888                     p!(write("[closure"));
889
890                     // FIXME(eddyb) should use `def_span`.
891                     if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
892                         if cx.tcx.sess.opts.debugging_opts.span_free_formats {
893                             p!(write("@{:?}", hir_id));
894                         } else {
895                             p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)));
896                         }
897                         let mut sep = " ";
898                         for (freevar, upvar_ty) in cx.tcx.freevars(did)
899                             .as_ref()
900                             .map_or(&[][..], |fv| &fv[..])
901                             .iter()
902                             .zip(upvar_tys)
903                         {
904                             p!(
905                                 write("{}{}:",
906                                         sep,
907                                         cx.tcx.hir().name(freevar.var_id())),
908                                 print(upvar_ty));
909                             sep = ", ";
910                         }
911                     } else {
912                         // cross-crate closure types should only be
913                         // visible in codegen bug reports, I imagine.
914                         p!(write("@{:?}", did));
915                         let mut sep = " ";
916                         for (index, upvar_ty) in upvar_tys.enumerate() {
917                             p!(
918                                    write("{}{}:", sep, index),
919                                    print(upvar_ty));
920                             sep = ", ";
921                         }
922                     }
923
924                     if cx.config.is_verbose {
925                         p!(write(
926                             " closure_kind_ty={:?} closure_sig_ty={:?}",
927                             substs.closure_kind_ty(did, cx.tcx),
928                             substs.closure_sig_ty(did, cx.tcx)
929                         ));
930                     }
931
932                     p!(write("]"))
933                 },
934                 Array(ty, sz) => {
935                     p!(write("["), print(ty), write("; "));
936                     match sz {
937                         ty::LazyConst::Unevaluated(_def_id, _substs) => {
938                             p!(write("_"));
939                         }
940                         ty::LazyConst::Evaluated(c) => {
941                             match c.val {
942                                 ConstValue::Infer(..) => p!(write("_")),
943                                 ConstValue::Param(ParamConst { name, .. }) =>
944                                     p!(write("{}", name)),
945                                 _ => p!(write("{}", c.unwrap_usize(cx.tcx))),
946                             }
947                         }
948                     }
949                     p!(write("]"))
950                 }
951                 Slice(ty) => {
952                     p!(write("["), print(ty), write("]"))
953                 }
954             }
955         }
956         debug {
957             p!(print_display(self))
958         }
959     }
960 }
961
962 define_print! {
963     ('tcx) ConstValue<'tcx>, (self, cx) {
964         display {
965             match self {
966                 ConstValue::Infer(..) => p!(write("_")),
967                 ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
968                 _ => p!(write("{:?}", self)),
969             }
970         }
971     }
972 }
973
974 define_print! {
975     ('tcx) ty::Const<'tcx>, (self, cx) {
976         display {
977             p!(write("{} : {}", self.val, self.ty))
978         }
979     }
980 }
981
982 define_print! {
983     ('tcx) ty::LazyConst<'tcx>, (self, cx) {
984         display {
985             match self {
986                 // FIXME(const_generics) this should print at least the type.
987                 ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
988                 ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
989             }
990         }
991     }
992 }
993
994 define_print! {
995     () ty::ParamTy, (self, cx) {
996         display {
997             p!(write("{}", self.name))
998         }
999         debug {
1000             p!(write("{}/#{}", self.name, self.idx))
1001         }
1002     }
1003 }
1004
1005 define_print! {
1006     () ty::ParamConst, (self, cx) {
1007         display {
1008             p!(write("{}", self.name))
1009         }
1010         debug {
1011             p!(write("{}/#{}", self.name, self.index))
1012         }
1013     }
1014 }
1015
1016 // Similar problem to `Binder<T>`, can't define a generic impl.
1017 define_print_multi! {
1018     [
1019     ('tcx) ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
1020     ('tcx) ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
1021     ]
1022     (self, cx) {
1023         display {
1024             p!(print(self.0), write(" : "), print(self.1))
1025         }
1026     }
1027 }
1028
1029 define_print! {
1030     ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) {
1031         display {
1032             p!(print(self.a), write(" <: "), print(self.b))
1033         }
1034     }
1035 }
1036
1037 define_print! {
1038     ('tcx) ty::TraitPredicate<'tcx>, (self, cx) {
1039         debug {
1040             p!(write("TraitPredicate({:?})",
1041                    self.trait_ref))
1042         }
1043         display {
1044             p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1045         }
1046     }
1047 }
1048
1049 define_print! {
1050     ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) {
1051         debug {
1052             p!(
1053                    write("ProjectionPredicate("),
1054                    print(self.projection_ty),
1055                    write(", "),
1056                    print(self.ty),
1057                    write(")"))
1058         }
1059         display {
1060             p!(print(self.projection_ty), write(" == "), print(self.ty))
1061         }
1062     }
1063 }
1064
1065 define_print! {
1066     ('tcx) ty::ProjectionTy<'tcx>, (self, cx) {
1067         display {
1068             nest!(|cx| cx.print_def_path(
1069                 self.item_def_id,
1070                 Some(self.substs),
1071                 Namespace::TypeNS,
1072                 iter::empty(),
1073             ));
1074         }
1075     }
1076 }
1077
1078 define_print! {
1079     () ty::ClosureKind, (self, cx) {
1080         display {
1081             match *self {
1082                 ty::ClosureKind::Fn => p!(write("Fn")),
1083                 ty::ClosureKind::FnMut => p!(write("FnMut")),
1084                 ty::ClosureKind::FnOnce => p!(write("FnOnce")),
1085             }
1086         }
1087     }
1088 }
1089
1090 define_print! {
1091     ('tcx) ty::Predicate<'tcx>, (self, cx) {
1092         display {
1093             match *self {
1094                 ty::Predicate::Trait(ref data) => p!(print(data)),
1095                 ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
1096                 ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
1097                 ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
1098                 ty::Predicate::Projection(ref predicate) => p!(print(predicate)),
1099                 ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
1100                 ty::Predicate::ObjectSafe(trait_def_id) => {
1101                     p!(write("the trait `"));
1102                     nest!(|cx| cx.print_def_path(
1103                         trait_def_id,
1104                         None,
1105                         Namespace::TypeNS,
1106                         iter::empty(),
1107                     ));
1108                     p!(write("` is object-safe"))
1109                 }
1110                 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
1111                     p!(write("the closure `"));
1112                     nest!(|cx| cx.print_def_path(
1113                         closure_def_id,
1114                         None,
1115                         Namespace::ValueNS,
1116                         iter::empty(),
1117                     ));
1118                     p!(write("` implements the trait `{}`", kind))
1119                 }
1120                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1121                     p!(write("the constant `"));
1122                     nest!(|cx| cx.print_def_path(
1123                         def_id,
1124                         Some(substs),
1125                         Namespace::ValueNS,
1126                         iter::empty(),
1127                     ));
1128                     p!(write("` can be evaluated"))
1129                 }
1130             }
1131         }
1132         debug {
1133             match *self {
1134                 ty::Predicate::Trait(ref a) => p!(print(a)),
1135                 ty::Predicate::Subtype(ref pair) => p!(print(pair)),
1136                 ty::Predicate::RegionOutlives(ref pair) => p!(print(pair)),
1137                 ty::Predicate::TypeOutlives(ref pair) => p!(print(pair)),
1138                 ty::Predicate::Projection(ref pair) => p!(print(pair)),
1139                 ty::Predicate::WellFormed(ty) => p!(print(ty)),
1140                 ty::Predicate::ObjectSafe(trait_def_id) => {
1141                     p!(write("ObjectSafe({:?})", trait_def_id))
1142                 }
1143                 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
1144                     p!(write("ClosureKind({:?}, {:?}, {:?})",
1145                         closure_def_id, closure_substs, kind))
1146                 }
1147                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1148                     p!(write("ConstEvaluatable({:?}, {:?})", def_id, substs))
1149                 }
1150             }
1151         }
1152     }
1153 }
1154
1155 define_print! {
1156     ('tcx) Kind<'tcx>, (self, cx) {
1157         display {
1158             match self.unpack() {
1159                 UnpackedKind::Lifetime(lt) => p!(print(lt)),
1160                 UnpackedKind::Type(ty) => p!(print(ty)),
1161                 UnpackedKind::Const(ct) => p!(print(ct)),
1162             }
1163         }
1164         debug {
1165             match self.unpack() {
1166                 UnpackedKind::Lifetime(lt) => p!(print(lt)),
1167                 UnpackedKind::Type(ty) => p!(print(ty)),
1168                 UnpackedKind::Const(ct) => p!(print(ct)),
1169             }
1170         }
1171     }
1172 }