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