]> git.lizzy.rs Git - rust.git/blob - src/librustc/util/ppaux.rs
rustc: don't pass Namespace explicitly, but rather track it in FmtPrinter.
[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, Namespace::TypeNS), |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, ns), |cx| {
266         let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
267         cx.print_def_path(did, Some(substs), 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(principal.def_id, None, iter::empty()));
288                             nest!(|cx| cx.fn_sig(args, false, proj.ty));
289                             resugared_principal = true;
290                         }
291                     }
292                 }
293
294                 if !resugared_principal {
295                     // Use a type that can't appear in defaults of type parameters.
296                     let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
297                     let principal = principal.with_self_ty(cx.tcx, dummy_self);
298                     nest!(|cx| cx.print_def_path(
299                         principal.def_id,
300                         Some(principal.substs),
301                         self.projection_bounds(),
302                     ));
303                 }
304                 first = false;
305             }
306
307             // Builtin bounds.
308             // FIXME(eddyb) avoid printing twice (needed to ensure
309             // that the auto traits are sorted *and* printed via cx).
310             let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
311                 (cx.tcx.def_path_str(did), did)
312             }).collect();
313
314             // The auto traits come ordered by `DefPathHash`. While
315             // `DefPathHash` is *stable* in the sense that it depends on
316             // neither the host nor the phase of the moon, it depends
317             // "pseudorandomly" on the compiler version and the target.
318             //
319             // To avoid that causing instabilities in compiletest
320             // output, sort the auto-traits alphabetically.
321             auto_traits.sort();
322
323             for (_, def_id) in auto_traits {
324                 if !first {
325                     p!(write(" + "));
326                 }
327                 first = false;
328
329                 nest!(|cx| cx.print_def_path(def_id, None, iter::empty()));
330             }
331         }
332     }
333 }
334
335 impl fmt::Debug for ty::GenericParamDef {
336     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337         let type_name = match self.kind {
338             ty::GenericParamDefKind::Lifetime => "Lifetime",
339             ty::GenericParamDefKind::Type { .. } => "Type",
340             ty::GenericParamDefKind::Const => "Const",
341         };
342         write!(f, "{}({}, {:?}, {})",
343                type_name,
344                self.name,
345                self.def_id,
346                self.index)
347     }
348 }
349
350 impl fmt::Debug for ty::TraitDef {
351     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
352         PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| {
353             cx.print_def_path(self.def_id, None, iter::empty())?;
354             Ok(())
355         })
356     }
357 }
358
359 impl fmt::Debug for ty::AdtDef {
360     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361         PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| {
362             cx.print_def_path(self.did, None, iter::empty())?;
363             Ok(())
364         })
365     }
366 }
367
368 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
369     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370         write!(f, "ClosureUpvar({:?},{:?})",
371                self.def,
372                self.ty)
373     }
374 }
375
376 impl fmt::Debug for ty::UpvarId {
377     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378         PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::ValueNS), |mut cx| {
379             define_scoped_cx!(cx);
380             p!(write("UpvarId({:?};`{}`;{:?})",
381                 self.var_path.hir_id,
382                 cx.tcx.hir().name_by_hir_id(self.var_path.hir_id),
383                 self.closure_expr_id));
384             Ok(())
385         })
386     }
387 }
388
389 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
390     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
391         write!(f, "UpvarBorrow({:?}, {:?})",
392                self.kind, self.region)
393     }
394 }
395
396 define_print! {
397     ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, cx) {
398         display {
399             p!(write("{{"));
400             let mut tys = self.iter();
401             if let Some(&ty) = tys.next() {
402                 p!(print(ty));
403                 for &ty in tys {
404                     p!(write(", "), print(ty));
405                 }
406             }
407             p!(write("}}"))
408         }
409     }
410 }
411
412 define_print! {
413     ('tcx) ty::TypeAndMut<'tcx>, (self, cx) {
414         display {
415             p!(
416                    write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
417                    print(self.ty))
418         }
419     }
420 }
421
422 define_print! {
423     ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) {
424         display {
425             let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
426
427             let trait_ref = *ty::Binder::bind(*self)
428                 .with_self_ty(cx.tcx, dummy_self)
429                 .skip_binder();
430             p!(print_display(trait_ref))
431         }
432         debug {
433             p!(print_display(self))
434         }
435     }
436 }
437
438 define_print! {
439     ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) {
440         debug {
441             p!(write("{:?} -> ", self.kind), print(self.target))
442         }
443     }
444 }
445
446 impl fmt::Debug for ty::BoundRegion {
447     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448         match *self {
449             ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
450             ty::BrFresh(n) => write!(f, "BrFresh({:?})", n),
451             ty::BrNamed(did, name) => {
452                 write!(f, "BrNamed({:?}:{:?}, {})",
453                         did.krate, did.index, name)
454             }
455             ty::BrEnv => write!(f, "BrEnv"),
456         }
457     }
458 }
459
460 define_print! {
461     () ty::RegionKind, (self, cx) {
462         display {
463             return cx.print_region(self);
464         }
465         debug {
466             match *self {
467                 ty::ReEarlyBound(ref data) => {
468                     p!(write("ReEarlyBound({}, {})",
469                            data.index,
470                            data.name))
471                 }
472
473                 ty::ReClosureBound(ref vid) => {
474                     p!(write("ReClosureBound({:?})", vid))
475                 }
476
477                 ty::ReLateBound(binder_id, ref bound_region) => {
478                     p!(write("ReLateBound({:?}, {:?})", binder_id, bound_region))
479                 }
480
481                 ty::ReFree(ref fr) => p!(print_debug(fr)),
482
483                 ty::ReScope(id) => {
484                     p!(write("ReScope({:?})", id))
485                 }
486
487                 ty::ReStatic => p!(write("ReStatic")),
488
489                 ty::ReVar(ref vid) => {
490                     p!(write("{:?}", vid));
491                 }
492
493                 ty::RePlaceholder(placeholder) => {
494                     p!(write("RePlaceholder({:?})", placeholder))
495                 }
496
497                 ty::ReEmpty => p!(write("ReEmpty")),
498
499                 ty::ReErased => p!(write("ReErased"))
500             }
501         }
502     }
503 }
504
505 define_print! {
506     () ty::FreeRegion, (self, cx) {
507         debug {
508             p!(write("ReFree({:?}, {:?})", self.scope, self.bound_region))
509         }
510     }
511 }
512
513 define_print! {
514     () ty::Variance, (self, cx) {
515         debug {
516             cx.printer.write_str(match *self {
517                 ty::Covariant => "+",
518                 ty::Contravariant => "-",
519                 ty::Invariant => "o",
520                 ty::Bivariant => "*",
521             })?
522         }
523     }
524 }
525
526 define_print! {
527     ('tcx) ty::FnSig<'tcx>, (self, cx) {
528         display {
529             if self.unsafety == hir::Unsafety::Unsafe {
530                 p!(write("unsafe "));
531             }
532
533             if self.abi != Abi::Rust {
534                 p!(write("extern {} ", self.abi));
535             }
536
537             p!(write("fn"));
538             nest!(|cx| cx.fn_sig(self.inputs(), self.c_variadic, self.output()));
539         }
540         debug {
541             p!(write("({:?}; c_variadic: {})->{:?}",
542                 self.inputs(), self.c_variadic, self.output()))
543         }
544     }
545 }
546
547 impl fmt::Debug for ty::TyVid {
548     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549         write!(f, "_#{}t", self.index)
550     }
551 }
552
553 impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
554     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
555         write!(f, "_#{}f", self.index)
556     }
557 }
558
559 impl fmt::Debug for ty::IntVid {
560     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561         write!(f, "_#{}i", self.index)
562     }
563 }
564
565 impl fmt::Debug for ty::FloatVid {
566     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567         write!(f, "_#{}f", self.index)
568     }
569 }
570
571 impl fmt::Debug for ty::RegionVid {
572     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
573         write!(f, "'_#{}r", self.index())
574     }
575 }
576
577 define_print! {
578     () ty::InferTy, (self, cx) {
579         display {
580             if cx.config.is_verbose {
581                 return self.print_debug(cx);
582             }
583             match *self {
584                 ty::TyVar(_) => p!(write("_")),
585                 ty::IntVar(_) => p!(write("{}", "{integer}")),
586                 ty::FloatVar(_) => p!(write("{}", "{float}")),
587                 ty::FreshTy(v) => p!(write("FreshTy({})", v)),
588                 ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)),
589                 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v))
590             }
591         }
592         debug {
593             match *self {
594                 ty::TyVar(ref v) => p!(write("{:?}", v)),
595                 ty::IntVar(ref v) => p!(write("{:?}", v)),
596                 ty::FloatVar(ref v) => p!(write("{:?}", v)),
597                 ty::FreshTy(v) => p!(write("FreshTy({:?})", v)),
598                 ty::FreshIntTy(v) => p!(write("FreshIntTy({:?})", v)),
599                 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({:?})", v))
600             }
601         }
602     }
603 }
604
605 impl fmt::Debug for ty::IntVarValue {
606     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
607         match *self {
608             ty::IntType(ref v) => v.fmt(f),
609             ty::UintType(ref v) => v.fmt(f),
610         }
611     }
612 }
613
614 impl fmt::Debug for ty::FloatVarValue {
615     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
616         self.0.fmt(f)
617     }
618 }
619
620 // The generic impl doesn't work yet because projections are not
621 // normalized under HRTB.
622 /*impl<T> fmt::Display for ty::Binder<T>
623     where T: fmt::Display + for<'a> ty::Lift<'a>,
624           for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
625 {
626     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627         PrintCx::with_tls_tcx(|cx| cx.in_binder(cx.tcx.lift(self)
628             .expect("could not lift for printing")))
629     }
630 }*/
631
632 define_print_multi! {
633     [
634     ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
635     ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
636     ('tcx) ty::Binder<ty::FnSig<'tcx>>,
637     ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
638     ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
639     ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
640     ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
641     ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
642     ]
643     (self, cx) {
644         display {
645             nest!(|cx| cx.in_binder(self))
646         }
647     }
648 }
649
650 define_print! {
651     ('tcx) ty::TraitRef<'tcx>, (self, cx) {
652         display {
653             nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty()));
654         }
655         debug {
656             nest!(|cx| cx.path_qualified(self.self_ty(), Some(*self)));
657         }
658     }
659 }
660
661 // FIXME(eddyb) move this to `ty::print`.
662 impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
663     pub fn pretty_print_type(
664         mut self,
665         ty: Ty<'tcx>,
666     ) -> Result<P::Type, P::Error> {
667         define_scoped_cx!(self);
668
669         match ty.sty {
670             ty::Bool => p!(write("bool")),
671             ty::Char => p!(write("char")),
672             ty::Int(t) => p!(write("{}", t.ty_to_string())),
673             ty::Uint(t) => p!(write("{}", t.ty_to_string())),
674             ty::Float(t) => p!(write("{}", t.ty_to_string())),
675             ty::RawPtr(ref tm) => {
676                 p!(write("*{} ", match tm.mutbl {
677                     hir::MutMutable => "mut",
678                     hir::MutImmutable => "const",
679                 }));
680                 p!(print(tm.ty))
681             }
682             ty::Ref(r, ty, mutbl) => {
683                 p!(write("&"));
684                 if self.print_region_outputs_anything(r) {
685                     p!(print_display(r), write(" "));
686                 }
687                 p!(print(ty::TypeAndMut { ty, mutbl }))
688             }
689             ty::Never => p!(write("!")),
690             ty::Tuple(ref tys) => {
691                 p!(write("("));
692                 let mut tys = tys.iter();
693                 if let Some(&ty) = tys.next() {
694                     p!(print(ty), write(","));
695                     if let Some(&ty) = tys.next() {
696                         p!(write(" "), print(ty));
697                         for &ty in tys {
698                             p!(write(", "), print(ty));
699                         }
700                     }
701                 }
702                 p!(write(")"))
703             }
704             ty::FnDef(def_id, substs) => {
705                 let sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs);
706                 p!(print(sig), write(" {{"));
707                 nest!(|cx| cx.print_value_path(def_id, Some(substs)));
708                 p!(write("}}"))
709             }
710             ty::FnPtr(ref bare_fn) => {
711                 p!(print(bare_fn))
712             }
713             ty::Infer(infer_ty) => p!(write("{}", infer_ty)),
714             ty::Error => p!(write("[type error]")),
715             ty::Param(ref param_ty) => p!(write("{}", param_ty)),
716             ty::Bound(debruijn, bound_ty) => {
717                 match bound_ty.kind {
718                     ty::BoundTyKind::Anon => {
719                         if debruijn == ty::INNERMOST {
720                             p!(write("^{}", bound_ty.var.index()))
721                         } else {
722                             p!(write("^{}_{}", debruijn.index(), bound_ty.var.index()))
723                         }
724                     }
725
726                     ty::BoundTyKind::Param(p) => p!(write("{}", p)),
727                 }
728             }
729             ty::Adt(def, substs) => {
730                 nest!(|cx| cx.print_def_path(def.did, Some(substs), iter::empty()));
731             }
732             ty::Dynamic(data, r) => {
733                 let print_r = self.print_region_outputs_anything(r);
734                 if print_r {
735                     p!(write("("));
736                 }
737                 p!(write("dyn "), print(data));
738                 if print_r {
739                     p!(write(" + "), print_display(r), write(")"));
740                 }
741             }
742             ty::Foreign(def_id) => {
743                 nest!(|cx| cx.print_def_path(def_id, None, iter::empty()));
744             }
745             ty::Projection(ref data) => p!(print(data)),
746             ty::UnnormalizedProjection(ref data) => {
747                 p!(write("Unnormalized("), print(data), write(")"))
748             }
749             ty::Placeholder(placeholder) => {
750                 p!(write("Placeholder({:?})", placeholder))
751             }
752             ty::Opaque(def_id, substs) => {
753                 if self.config.is_verbose {
754                     p!(write("Opaque({:?}, {:?})", def_id, substs));
755                     return Ok(self.printer);
756                 }
757
758                 let def_key = self.tcx.def_key(def_id);
759                 if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
760                     p!(write("{}", name));
761                     let mut substs = substs.iter();
762                     // FIXME(eddyb) print this with `print_def_path`.
763                     if let Some(first) = substs.next() {
764                         p!(write("::<"));
765                         p!(print_display(first));
766                         for subst in substs {
767                             p!(write(", "), print_display(subst));
768                         }
769                         p!(write(">"));
770                     }
771                     return Ok(self.printer);
772                 }
773                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
774                 // by looking up the projections associated with the def_id.
775                 let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs);
776
777                 let mut first = true;
778                 let mut is_sized = false;
779                 p!(write("impl"));
780                 for predicate in bounds.predicates {
781                     if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
782                         // Don't print +Sized, but rather +?Sized if absent.
783                         if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
784                             is_sized = true;
785                             continue;
786                         }
787
788                         p!(
789                                 write("{}", if first { " " } else { "+" }),
790                                 print(trait_ref));
791                         first = false;
792                     }
793                 }
794                 if !is_sized {
795                     p!(write("{}?Sized", if first { " " } else { "+" }));
796                 } else if first {
797                     p!(write(" Sized"));
798                 }
799             }
800             ty::Str => p!(write("str")),
801             ty::Generator(did, substs, movability) => {
802                 let upvar_tys = substs.upvar_tys(did, self.tcx);
803                 let witness = substs.witness(did, self.tcx);
804                 if movability == hir::GeneratorMovability::Movable {
805                     p!(write("[generator"));
806                 } else {
807                     p!(write("[static generator"));
808                 }
809
810                 // FIXME(eddyb) should use `def_span`.
811                 if let Some(hir_id) = self.tcx.hir().as_local_hir_id(did) {
812                     p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_id)));
813                     let mut sep = " ";
814                     for (freevar, upvar_ty) in self.tcx.freevars(did)
815                         .as_ref()
816                         .map_or(&[][..], |fv| &fv[..])
817                         .iter()
818                         .zip(upvar_tys)
819                     {
820                         p!(
821                             write("{}{}:",
822                                     sep,
823                                     self.tcx.hir().name(freevar.var_id())),
824                             print(upvar_ty));
825                         sep = ", ";
826                     }
827                 } else {
828                     // cross-crate closure types should only be
829                     // visible in codegen bug reports, I imagine.
830                     p!(write("@{:?}", did));
831                     let mut sep = " ";
832                     for (index, upvar_ty) in upvar_tys.enumerate() {
833                         p!(
834                                 write("{}{}:", sep, index),
835                                 print(upvar_ty));
836                         sep = ", ";
837                     }
838                 }
839
840                 p!(write(" "), print(witness), write("]"))
841             },
842             ty::GeneratorWitness(types) => {
843                 nest!(|cx| cx.in_binder(&types))
844             }
845             ty::Closure(did, substs) => {
846                 let upvar_tys = substs.upvar_tys(did, self.tcx);
847                 p!(write("[closure"));
848
849                 // FIXME(eddyb) should use `def_span`.
850                 if let Some(hir_id) = self.tcx.hir().as_local_hir_id(did) {
851                     if self.tcx.sess.opts.debugging_opts.span_free_formats {
852                         p!(write("@{:?}", hir_id));
853                     } else {
854                         p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_id)));
855                     }
856                     let mut sep = " ";
857                     for (freevar, upvar_ty) in self.tcx.freevars(did)
858                         .as_ref()
859                         .map_or(&[][..], |fv| &fv[..])
860                         .iter()
861                         .zip(upvar_tys)
862                     {
863                         p!(
864                             write("{}{}:",
865                                     sep,
866                                     self.tcx.hir().name(freevar.var_id())),
867                             print(upvar_ty));
868                         sep = ", ";
869                     }
870                 } else {
871                     // cross-crate closure types should only be
872                     // visible in codegen bug reports, I imagine.
873                     p!(write("@{:?}", did));
874                     let mut sep = " ";
875                     for (index, upvar_ty) in upvar_tys.enumerate() {
876                         p!(
877                                 write("{}{}:", sep, index),
878                                 print(upvar_ty));
879                         sep = ", ";
880                     }
881                 }
882
883                 if self.config.is_verbose {
884                     p!(write(
885                         " closure_kind_ty={:?} closure_sig_ty={:?}",
886                         substs.closure_kind_ty(did, self.tcx),
887                         substs.closure_sig_ty(did, self.tcx)
888                     ));
889                 }
890
891                 p!(write("]"))
892             },
893             ty::Array(ty, sz) => {
894                 p!(write("["), print(ty), write("; "));
895                 match sz {
896                     ty::LazyConst::Unevaluated(_def_id, _substs) => {
897                         p!(write("_"));
898                     }
899                     ty::LazyConst::Evaluated(c) => {
900                         match c.val {
901                             ConstValue::Infer(..) => p!(write("_")),
902                             ConstValue::Param(ParamConst { name, .. }) =>
903                                 p!(write("{}", name)),
904                             _ => p!(write("{}", c.unwrap_usize(self.tcx))),
905                         }
906                     }
907                 }
908                 p!(write("]"))
909             }
910             ty::Slice(ty) => {
911                 p!(write("["), print(ty), write("]"))
912             }
913         }
914
915         Ok(self.printer)
916     }
917 }
918
919 define_print! {
920     ('tcx) Ty<'tcx>, (self, cx) {
921         display {
922             return cx.print_type(self);
923         }
924         debug {
925             p!(print_display(self))
926         }
927     }
928 }
929
930 define_print! {
931     ('tcx) ConstValue<'tcx>, (self, cx) {
932         display {
933             match self {
934                 ConstValue::Infer(..) => p!(write("_")),
935                 ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
936                 _ => p!(write("{:?}", self)),
937             }
938         }
939     }
940 }
941
942 define_print! {
943     ('tcx) ty::Const<'tcx>, (self, cx) {
944         display {
945             p!(write("{} : {}", self.val, self.ty))
946         }
947     }
948 }
949
950 define_print! {
951     ('tcx) ty::LazyConst<'tcx>, (self, cx) {
952         display {
953             match self {
954                 // FIXME(const_generics) this should print at least the type.
955                 ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
956                 ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
957             }
958         }
959     }
960 }
961
962 define_print! {
963     () ty::ParamTy, (self, cx) {
964         display {
965             p!(write("{}", self.name))
966         }
967         debug {
968             p!(write("{}/#{}", self.name, self.idx))
969         }
970     }
971 }
972
973 define_print! {
974     () ty::ParamConst, (self, cx) {
975         display {
976             p!(write("{}", self.name))
977         }
978         debug {
979             p!(write("{}/#{}", self.name, self.index))
980         }
981     }
982 }
983
984 // Similar problem to `Binder<T>`, can't define a generic impl.
985 define_print_multi! {
986     [
987     ('tcx) ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
988     ('tcx) ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
989     ]
990     (self, cx) {
991         display {
992             p!(print(self.0), write(" : "), print(self.1))
993         }
994     }
995 }
996
997 define_print! {
998     ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) {
999         display {
1000             p!(print(self.a), write(" <: "), print(self.b))
1001         }
1002     }
1003 }
1004
1005 define_print! {
1006     ('tcx) ty::TraitPredicate<'tcx>, (self, cx) {
1007         debug {
1008             p!(write("TraitPredicate({:?})",
1009                    self.trait_ref))
1010         }
1011         display {
1012             p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1013         }
1014     }
1015 }
1016
1017 define_print! {
1018     ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) {
1019         debug {
1020             p!(
1021                    write("ProjectionPredicate("),
1022                    print(self.projection_ty),
1023                    write(", "),
1024                    print(self.ty),
1025                    write(")"))
1026         }
1027         display {
1028             p!(print(self.projection_ty), write(" == "), print(self.ty))
1029         }
1030     }
1031 }
1032
1033 define_print! {
1034     ('tcx) ty::ProjectionTy<'tcx>, (self, cx) {
1035         display {
1036             nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty()));
1037         }
1038     }
1039 }
1040
1041 define_print! {
1042     () ty::ClosureKind, (self, cx) {
1043         display {
1044             match *self {
1045                 ty::ClosureKind::Fn => p!(write("Fn")),
1046                 ty::ClosureKind::FnMut => p!(write("FnMut")),
1047                 ty::ClosureKind::FnOnce => p!(write("FnOnce")),
1048             }
1049         }
1050     }
1051 }
1052
1053 define_print! {
1054     ('tcx) ty::Predicate<'tcx>, (self, cx) {
1055         display {
1056             match *self {
1057                 ty::Predicate::Trait(ref data) => p!(print(data)),
1058                 ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
1059                 ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
1060                 ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
1061                 ty::Predicate::Projection(ref predicate) => p!(print(predicate)),
1062                 ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
1063                 ty::Predicate::ObjectSafe(trait_def_id) => {
1064                     p!(write("the trait `"));
1065                     nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty()));
1066                     p!(write("` is object-safe"))
1067                 }
1068                 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
1069                     p!(write("the closure `"));
1070                     nest!(|cx| cx.print_value_path(closure_def_id, None));
1071                     p!(write("` implements the trait `{}`", kind))
1072                 }
1073                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1074                     p!(write("the constant `"));
1075                     nest!(|cx| cx.print_value_path(def_id, Some(substs)));
1076                     p!(write("` can be evaluated"))
1077                 }
1078             }
1079         }
1080         debug {
1081             match *self {
1082                 ty::Predicate::Trait(ref a) => p!(print(a)),
1083                 ty::Predicate::Subtype(ref pair) => p!(print(pair)),
1084                 ty::Predicate::RegionOutlives(ref pair) => p!(print(pair)),
1085                 ty::Predicate::TypeOutlives(ref pair) => p!(print(pair)),
1086                 ty::Predicate::Projection(ref pair) => p!(print(pair)),
1087                 ty::Predicate::WellFormed(ty) => p!(print(ty)),
1088                 ty::Predicate::ObjectSafe(trait_def_id) => {
1089                     p!(write("ObjectSafe({:?})", trait_def_id))
1090                 }
1091                 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
1092                     p!(write("ClosureKind({:?}, {:?}, {:?})",
1093                         closure_def_id, closure_substs, kind))
1094                 }
1095                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1096                     p!(write("ConstEvaluatable({:?}, {:?})", def_id, substs))
1097                 }
1098             }
1099         }
1100     }
1101 }
1102
1103 define_print! {
1104     ('tcx) Kind<'tcx>, (self, cx) {
1105         display {
1106             match self.unpack() {
1107                 UnpackedKind::Lifetime(lt) => p!(print(lt)),
1108                 UnpackedKind::Type(ty) => p!(print(ty)),
1109                 UnpackedKind::Const(ct) => p!(print(ct)),
1110             }
1111         }
1112         debug {
1113             match self.unpack() {
1114                 UnpackedKind::Lifetime(lt) => p!(print(lt)),
1115                 UnpackedKind::Type(ty) => p!(print(ty)),
1116                 UnpackedKind::Const(ct) => p!(print(ct)),
1117             }
1118         }
1119     }
1120 }