1 use crate::hir::def::Namespace;
2 use crate::hir::def_id::DefId;
3 use crate::middle::region;
4 use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind};
5 use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed};
6 use crate::ty::{Bool, Char, Adt};
7 use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
8 use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
9 use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
10 use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
11 use crate::ty::{self, ParamConst, Ty, TypeFoldable};
12 use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer};
13 use crate::mir::interpret::ConstValue;
15 use std::fmt::{self, Write as _};
19 use rustc_target::spec::abi::Abi;
20 use syntax::ast::CRATE_NODE_ID;
21 use syntax::symbol::{Symbol, InternedString};
24 macro_rules! gen_display_debug_body {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| {
28 $with(&cx.tcx.lift(self).expect("could not lift for printing"), cx)?;
34 macro_rules! gen_display_debug {
35 ( ($($x:tt)+) $target:ty, display yes ) => {
36 impl<$($x)+> fmt::Display for $target {
37 gen_display_debug_body! { Print::print_display }
40 ( () $target:ty, display yes ) => {
41 impl fmt::Display for $target {
42 gen_display_debug_body! { Print::print_display }
45 ( ($($x:tt)+) $target:ty, debug yes ) => {
46 impl<$($x)+> fmt::Debug for $target {
47 gen_display_debug_body! { Print::print_debug }
50 ( () $target:ty, debug yes ) => {
51 impl fmt::Debug for $target {
52 gen_display_debug_body! { Print::print_debug }
55 ( $generic:tt $target:ty, $t:ident no ) => {};
57 macro_rules! gen_print_impl {
58 ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
59 impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target {
61 type Error = fmt::Error;
62 fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
66 define_scoped_cx!($cx);
68 if $cx.config.is_debug $dbg
75 ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
76 impl<P: PrettyPrinter> Print<'tcx, P> for $target {
78 type Error = fmt::Error;
79 fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
83 define_scoped_cx!($cx);
85 if $cx.config.is_debug $dbg
92 ( $generic:tt $target:ty,
93 $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
94 gen_print_impl! { $generic $target, $vars $disp $dbg }
95 gen_display_debug! { $generic $target, display $gendisp }
96 gen_display_debug! { $generic $target, debug $gendbg }
99 macro_rules! define_print {
100 ( $generic:tt $target:ty,
101 $vars:tt { display $disp:block debug $dbg:block } ) => {
102 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
104 ( $generic:tt $target:ty,
105 $vars:tt { debug $dbg:block display $disp:block } ) => {
106 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
108 ( $generic:tt $target:ty,
109 $vars:tt { debug $dbg:block } ) => {
110 gen_print_impl! { $generic $target, $vars no {
111 bug!(concat!("display not implemented for ", stringify!($target)));
114 ( $generic:tt $target:ty,
115 ($self:ident, $cx:ident) { display $disp:block } ) => {
116 gen_print_impl! { $generic $target, ($self, $cx) yes $disp no {
117 write!($cx.printer, "{:?}", $self)?
121 macro_rules! define_print_multi {
122 ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
123 $(define_print! { $generic $target, $vars $def })*
128 scoped_cx!() = scoped_cx!().nest($closure)?
131 macro_rules! print_inner {
132 (write ($($data:expr),+)) => {
133 write!(scoped_cx!().printer, $($data),+)?
135 ($kind:ident ($data:expr)) => {
136 nest!(|cx| $data.$kind(cx))
140 ($($kind:ident $data:tt),+) => {
142 $(print_inner!($kind $data));+
146 macro_rules! define_scoped_cx {
148 #[allow(unused_macros)]
149 macro_rules! scoped_cx {
155 impl<P: PrettyPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
161 ) -> Result<P, fmt::Error> {
162 define_scoped_cx!(self);
165 let mut inputs = inputs.iter();
166 if let Some(&ty) = inputs.next() {
167 p!(print_display(ty));
169 p!(write(", "), print_display(ty));
176 if !output.is_unit() {
177 p!(write(" -> "), print_display(output));
183 fn in_binder<T>(mut self, value: &ty::Binder<T>) -> Result<P, fmt::Error>
184 where T: Print<'tcx, P, Output = P, Error = fmt::Error> + TypeFoldable<'tcx>
186 fn name_by_region_index(index: usize) -> InternedString {
188 0 => Symbol::intern("'r"),
189 1 => Symbol::intern("'s"),
190 i => Symbol::intern(&format!("'t{}", i-2)),
194 // Replace any anonymous late-bound regions with named
195 // variants, using gensym'd identifiers, so that we can
196 // clearly differentiate between named and unnamed regions in
197 // the output. We'll probably want to tweak this over time to
198 // decide just how much information to give.
199 if self.config.binder_depth == 0 {
200 self.prepare_late_bound_region_info(value);
203 let mut empty = true;
204 let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
205 write!(cx.printer, "{}", if empty {
213 // NOTE(eddyb) this must be below `start_or_continue`'s definition
214 // as that also has a `define_scoped_cx` and that kind of shadowing
215 // is disallowed (name resolution thinks `scoped_cx!` is ambiguous).
216 define_scoped_cx!(self);
218 let old_region_index = self.config.region_index;
219 let mut region_index = old_region_index;
220 let new_value = self.tcx.replace_late_bound_regions(value, |br| {
221 let _ = start_or_continue(&mut self, "for<", ", ");
223 ty::BrNamed(_, name) => {
224 let _ = write!(self.printer, "{}", name);
231 let name = name_by_region_index(region_index);
233 if !self.is_name_used(&name) {
237 let _ = write!(self.printer, "{}", name);
238 ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name)
241 self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
243 start_or_continue(&mut self, "", "> ")?;
245 // Push current state to gcx, and restore after writing new_value.
246 self.config.binder_depth += 1;
247 self.config.region_index = region_index;
248 let result = new_value.print_display(PrintCx {
250 printer: self.printer,
253 self.config.region_index = old_region_index;
254 self.config.binder_depth -= 1;
258 fn is_name_used(&self, name: &InternedString) -> bool {
259 match self.config.used_region_names {
260 Some(ref names) => names.contains(name),
266 pub fn parameterized<F: fmt::Write>(
269 substs: SubstsRef<'_>,
272 PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| {
273 let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
274 cx.print_def_path(did, Some(substs), ns, iter::empty())?;
280 ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, cx) {
282 // Generate the main trait ref, including associated types.
283 let mut first = true;
285 if let Some(principal) = self.principal() {
286 let mut resugared_principal = false;
288 // Special-case `Fn(...) -> ...` and resugar it.
289 let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id);
290 if !cx.config.is_verbose && fn_trait_kind.is_some() {
291 if let ty::Tuple(ref args) = principal.substs.type_at(0).sty {
292 let mut projections = self.projection_bounds();
293 if let (Some(proj), None) = (projections.next(), projections.next()) {
294 nest!(|cx| cx.print_def_path(
300 nest!(|cx| cx.fn_sig(args, false, proj.ty));
301 resugared_principal = true;
306 if !resugared_principal {
307 // Use a type that can't appear in defaults of type parameters.
308 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
309 let principal = principal.with_self_ty(cx.tcx, dummy_self);
310 nest!(|cx| cx.print_def_path(
312 Some(principal.substs),
314 self.projection_bounds(),
321 // FIXME(eddyb) avoid printing twice (needed to ensure
322 // that the auto traits are sorted *and* printed via cx).
323 let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
324 (cx.tcx.def_path_str(did), did)
327 // The auto traits come ordered by `DefPathHash`. While
328 // `DefPathHash` is *stable* in the sense that it depends on
329 // neither the host nor the phase of the moon, it depends
330 // "pseudorandomly" on the compiler version and the target.
332 // To avoid that causing instabilities in compiletest
333 // output, sort the auto-traits alphabetically.
336 for (_, def_id) in auto_traits {
342 nest!(|cx| cx.print_def_path(
353 impl fmt::Debug for ty::GenericParamDef {
354 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355 let type_name = match self.kind {
356 ty::GenericParamDefKind::Lifetime => "Lifetime",
357 ty::GenericParamDefKind::Type { .. } => "Type",
358 ty::GenericParamDefKind::Const => "Const",
360 write!(f, "{}({}, {:?}, {})",
368 impl fmt::Debug for ty::TraitDef {
369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370 PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| {
382 impl fmt::Debug for ty::AdtDef {
383 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384 PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| {
396 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
397 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
398 write!(f, "ClosureUpvar({:?},{:?})",
404 impl fmt::Debug for ty::UpvarId {
405 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
406 PrintCx::with_tls_tcx(FmtPrinter::new(f), |mut cx| {
407 define_scoped_cx!(cx);
408 p!(write("UpvarId({:?};`{}`;{:?})",
409 self.var_path.hir_id,
410 cx.tcx.hir().name_by_hir_id(self.var_path.hir_id),
411 self.closure_expr_id));
417 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 write!(f, "UpvarBorrow({:?}, {:?})",
420 self.kind, self.region)
425 ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, cx) {
428 let mut tys = self.iter();
429 if let Some(&ty) = tys.next() {
432 p!(write(", "), print(ty));
441 ('tcx) ty::TypeAndMut<'tcx>, (self, cx) {
444 write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
451 ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) {
453 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
455 let trait_ref = *ty::Binder::bind(*self)
456 .with_self_ty(cx.tcx, dummy_self)
458 p!(print_display(trait_ref))
461 p!(print_display(self))
467 ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) {
469 p!(write("{:?} -> ", self.kind), print(self.target))
475 () ty::BoundRegion, (self, cx) {
477 if cx.config.is_verbose {
478 return self.print_debug(cx);
481 if let BrNamed(_, name) = *self {
482 if name != "" && name != "'_" {
483 p!(write("{}", name));
484 return Ok(cx.printer);
488 let highlight = cx.printer.region_highlight_mode();
489 if let Some((region, counter)) = highlight.highlight_bound_region {
491 p!(write("'{}", counter));
497 BrAnon(n) => p!(write("BrAnon({:?})", n)),
498 BrFresh(n) => p!(write("BrFresh({:?})", n)),
499 BrNamed(did, name) => {
500 p!(write("BrNamed({:?}:{:?}, {})",
501 did.krate, did.index, name))
503 BrEnv => p!(write("BrEnv")),
509 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
511 // NB: this must be kept in sync with the printing logic above.
512 impl ty::BoundRegion {
513 fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
514 where P: PrettyPrinter
516 if cx.config.is_verbose {
520 if let BrNamed(_, name) = *self {
521 if name != "" && name != "'_" {
526 let highlight = cx.printer.region_highlight_mode();
527 if let Some((region, _)) = highlight.highlight_bound_region {
538 () ty::PlaceholderRegion, (self, cx) {
540 if cx.config.is_verbose {
541 return self.print_debug(cx);
544 let highlight = cx.printer.region_highlight_mode();
545 if let Some(counter) = highlight.placeholder_highlight(*self) {
546 p!(write("'{}", counter));
548 p!(print_display(self.name));
554 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
556 // NB: this must be kept in sync with the printing logic above.
557 impl ty::PlaceholderRegion {
558 fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
559 where P: PrettyPrinter
561 if cx.config.is_verbose {
565 let highlight = cx.printer.region_highlight_mode();
566 if highlight.placeholder_highlight(*self).is_some() {
570 self.name.display_outputs_anything(cx)
575 () ty::RegionKind, (self, cx) {
577 if cx.config.is_verbose {
578 return self.print_debug(cx);
581 // Watch out for region highlights.
582 if let Some(n) = cx.printer.region_highlight_mode().region_highlighted(self) {
584 return Ok(cx.printer);
587 // These printouts are concise. They do not contain all the information
588 // the user might want to diagnose an error, but there is basically no way
589 // to fit that into a short string. Hence the recommendation to use
590 // `explain_region()` or `note_and_explain_region()`.
592 ty::ReEarlyBound(ref data) => {
593 if data.name != "'_" {
594 p!(write("{}", data.name))
597 ty::ReLateBound(_, br) |
598 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
599 p!(print_display(br))
601 ty::RePlaceholder(p) => {
604 ty::ReScope(scope) if cx.config.identify_regions => {
606 region::ScopeData::Node =>
607 p!(write("'{}s", scope.item_local_id().as_usize())),
608 region::ScopeData::CallSite =>
609 p!(write("'{}cs", scope.item_local_id().as_usize())),
610 region::ScopeData::Arguments =>
611 p!(write("'{}as", scope.item_local_id().as_usize())),
612 region::ScopeData::Destruction =>
613 p!(write("'{}ds", scope.item_local_id().as_usize())),
614 region::ScopeData::Remainder(first_statement_index) => p!(write(
616 scope.item_local_id().as_usize(),
617 first_statement_index.index()
621 ty::ReVar(region_vid) if cx.config.identify_regions => {
622 p!(print_debug(region_vid))
624 ty::ReVar(region_vid) => {
625 p!(print_display(region_vid))
629 ty::ReStatic => p!(write("'static")),
630 ty::ReEmpty => p!(write("'<empty>")),
632 // The user should never encounter these in unsubstituted form.
633 ty::ReClosureBound(vid) => p!(write("{:?}", vid)),
638 ty::ReEarlyBound(ref data) => {
639 p!(write("ReEarlyBound({}, {})",
644 ty::ReClosureBound(ref vid) => {
645 p!(write("ReClosureBound({:?})",
649 ty::ReLateBound(binder_id, ref bound_region) => {
650 p!(write("ReLateBound({:?}, ", binder_id),
651 print_debug(bound_region),
655 ty::ReFree(ref fr) => p!(print_debug(fr)),
658 p!(write("ReScope({:?})", id))
661 ty::ReStatic => p!(write("ReStatic")),
663 ty::ReVar(ref vid) => {
667 ty::RePlaceholder(placeholder) => {
668 p!(write("RePlaceholder("), print_debug(placeholder), write(")"))
671 ty::ReEmpty => p!(write("ReEmpty")),
673 ty::ReErased => p!(write("ReErased"))
679 // HACK(eddyb) Trying to print a lifetime might not print anything, which
680 // may need special handling in the caller (of `ty::RegionKind::print`).
681 // To avoid printing to a temporary string, the `display_outputs_anything`
682 // method can instead be used to determine this, ahead of time.
684 // NB: this must be kept in sync with the printing logic above.
685 impl ty::RegionKind {
686 // HACK(eddyb) `pub(crate)` only for `ty::print`.
687 pub(crate) fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
688 where P: PrettyPrinter
690 if cx.config.is_verbose {
694 if cx.printer.region_highlight_mode().region_highlighted(self).is_some() {
699 ty::ReEarlyBound(ref data) => {
700 data.name != "" && data.name != "'_"
703 ty::ReLateBound(_, br) |
704 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
705 br.display_outputs_anything(cx)
708 ty::RePlaceholder(p) => p.display_outputs_anything(cx),
711 ty::ReVar(_) if cx.config.identify_regions => true,
713 ty::ReVar(region_vid) => region_vid.display_outputs_anything(cx),
716 ty::ReErased => false,
720 ty::ReClosureBound(_) => true,
726 () ty::FreeRegion, (self, cx) {
728 p!(write("ReFree({:?}, {:?})", self.scope, self.bound_region))
734 () ty::Variance, (self, cx) {
736 cx.printer.write_str(match *self {
737 ty::Covariant => "+",
738 ty::Contravariant => "-",
739 ty::Invariant => "o",
740 ty::Bivariant => "*",
747 ('tcx) ty::FnSig<'tcx>, (self, cx) {
749 if self.unsafety == hir::Unsafety::Unsafe {
750 p!(write("unsafe "));
753 if self.abi != Abi::Rust {
754 p!(write("extern {} ", self.abi));
758 nest!(|cx| cx.fn_sig(self.inputs(), self.c_variadic, self.output()));
761 p!(write("({:?}; c_variadic: {})->{:?}",
762 self.inputs(), self.c_variadic, self.output()))
767 impl fmt::Debug for ty::TyVid {
768 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
769 write!(f, "_#{}t", self.index)
773 impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
774 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
775 write!(f, "_#{}f", self.index)
779 impl fmt::Debug for ty::IntVid {
780 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
781 write!(f, "_#{}i", self.index)
785 impl fmt::Debug for ty::FloatVid {
786 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
787 write!(f, "_#{}f", self.index)
792 () ty::RegionVid, (self, cx) {
794 if cx.config.is_verbose {
795 return self.print_debug(cx);
798 let highlight = cx.printer.region_highlight_mode();
799 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
800 p!(write("'{}", counter));
804 // HACK(eddyb) this is duplicated from `display` printing,
805 // to keep NLL borrowck working even with `-Zverbose`.
806 let highlight = cx.printer.region_highlight_mode();
807 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
808 p!(write("'{}", counter));
810 p!(write("'_#{}r", self.index()));
816 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
818 // NB: this must be kept in sync with the printing logic above.
820 fn display_outputs_anything<P>(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool
821 where P: PrettyPrinter
823 if cx.config.is_verbose {
827 let highlight = cx.printer.region_highlight_mode();
828 if highlight.region_highlighted(&ty::ReVar(*self)).is_some() {
837 () ty::InferTy, (self, cx) {
839 if cx.config.is_verbose {
840 return self.print_debug(cx);
843 ty::TyVar(_) => p!(write("_")),
844 ty::IntVar(_) => p!(write("{}", "{integer}")),
845 ty::FloatVar(_) => p!(write("{}", "{float}")),
846 ty::FreshTy(v) => p!(write("FreshTy({})", v)),
847 ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)),
848 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v))
853 ty::TyVar(ref v) => p!(write("{:?}", v)),
854 ty::IntVar(ref v) => p!(write("{:?}", v)),
855 ty::FloatVar(ref v) => p!(write("{:?}", v)),
856 ty::FreshTy(v) => p!(write("FreshTy({:?})", v)),
857 ty::FreshIntTy(v) => p!(write("FreshIntTy({:?})", v)),
858 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({:?})", v))
864 impl fmt::Debug for ty::IntVarValue {
865 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
867 ty::IntType(ref v) => v.fmt(f),
868 ty::UintType(ref v) => v.fmt(f),
873 impl fmt::Debug for ty::FloatVarValue {
874 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
879 // The generic impl doesn't work yet because projections are not
880 // normalized under HRTB.
881 /*impl<T> fmt::Display for ty::Binder<T>
882 where T: fmt::Display + for<'a> ty::Lift<'a>,
883 for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
885 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
886 PrintCx::with_tls_tcx(|cx| cx.in_binder(cx.tcx.lift(self)
887 .expect("could not lift for printing")))
891 define_print_multi! {
893 ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
894 ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
895 ('tcx) ty::Binder<ty::FnSig<'tcx>>,
896 ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
897 ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
898 ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
899 ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
900 ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
904 nest!(|cx| cx.in_binder(self))
910 ('tcx) ty::TraitRef<'tcx>, (self, cx) {
912 nest!(|cx| cx.print_def_path(
920 nest!(|cx| cx.path_qualified(self.self_ty(), Some(*self), Namespace::TypeNS));
926 ('tcx) ty::Ty<'tcx>, (self, cx) {
929 Bool => p!(write("bool")),
930 Char => p!(write("char")),
931 Int(t) => p!(write("{}", t.ty_to_string())),
932 Uint(t) => p!(write("{}", t.ty_to_string())),
933 Float(t) => p!(write("{}", t.ty_to_string())),
935 p!(write("*{} ", match tm.mutbl {
936 hir::MutMutable => "mut",
937 hir::MutImmutable => "const",
941 Ref(r, ty, mutbl) => {
943 if r.display_outputs_anything(&cx) {
944 p!(print_display(r), write(" "));
946 p!(print(ty::TypeAndMut { ty, mutbl }))
948 Never => p!(write("!")),
951 let mut tys = tys.iter();
952 if let Some(&ty) = tys.next() {
953 p!(print(ty), write(","));
954 if let Some(&ty) = tys.next() {
955 p!(write(" "), print(ty));
957 p!(write(", "), print(ty));
963 FnDef(def_id, substs) => {
964 let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs);
965 p!(print(sig), write(" {{"));
966 nest!(|cx| cx.print_def_path(
974 FnPtr(ref bare_fn) => {
977 Infer(infer_ty) => p!(write("{}", infer_ty)),
978 Error => p!(write("[type error]")),
979 Param(ref param_ty) => p!(write("{}", param_ty)),
980 Bound(debruijn, bound_ty) => {
981 match bound_ty.kind {
982 ty::BoundTyKind::Anon => {
983 if debruijn == ty::INNERMOST {
984 p!(write("^{}", bound_ty.var.index()))
986 p!(write("^{}_{}", debruijn.index(), bound_ty.var.index()))
990 ty::BoundTyKind::Param(p) => p!(write("{}", p)),
993 Adt(def, substs) => {
994 nest!(|cx| cx.print_def_path(
1001 Dynamic(data, r) => {
1002 let print_r = r.display_outputs_anything(&cx);
1006 p!(write("dyn "), print(data));
1008 p!(write(" + "), print_display(r), write(")"));
1011 Foreign(def_id) => {
1012 nest!(|cx| cx.print_def_path(
1019 Projection(ref data) => p!(print(data)),
1020 UnnormalizedProjection(ref data) => {
1021 p!(write("Unnormalized("), print(data), write(")"))
1023 Placeholder(placeholder) => {
1024 p!(write("Placeholder({:?})", placeholder))
1026 Opaque(def_id, substs) => {
1027 if cx.config.is_verbose {
1028 p!(write("Opaque({:?}, {:?})", def_id, substs));
1029 return Ok(cx.printer);
1032 let def_key = cx.tcx.def_key(def_id);
1033 if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
1034 p!(write("{}", name));
1035 let mut substs = substs.iter();
1036 // FIXME(eddyb) print this with `print_def_path`.
1037 if let Some(first) = substs.next() {
1039 p!(print_display(first));
1040 for subst in substs {
1041 p!(write(", "), print_display(subst));
1045 return Ok(cx.printer);
1047 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1048 // by looking up the projections associated with the def_id.
1049 let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs);
1051 let mut first = true;
1052 let mut is_sized = false;
1054 for predicate in bounds.predicates {
1055 if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
1056 // Don't print +Sized, but rather +?Sized if absent.
1057 if Some(trait_ref.def_id()) == cx.tcx.lang_items().sized_trait() {
1063 write("{}", if first { " " } else { "+" }),
1069 p!(write("{}?Sized", if first { " " } else { "+" }));
1071 p!(write(" Sized"));
1074 Str => p!(write("str")),
1075 Generator(did, substs, movability) => {
1076 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1077 let witness = substs.witness(did, cx.tcx);
1078 if movability == hir::GeneratorMovability::Movable {
1079 p!(write("[generator"));
1081 p!(write("[static generator"));
1084 // FIXME(eddyb) should use `def_span`.
1085 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1086 p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)));
1088 for (freevar, upvar_ty) in cx.tcx.freevars(did)
1090 .map_or(&[][..], |fv| &fv[..])
1097 cx.tcx.hir().name(freevar.var_id())),
1102 // cross-crate closure types should only be
1103 // visible in codegen bug reports, I imagine.
1104 p!(write("@{:?}", did));
1106 for (index, upvar_ty) in upvar_tys.enumerate() {
1108 write("{}{}:", sep, index),
1114 p!(write(" "), print(witness), write("]"))
1116 GeneratorWitness(types) => {
1117 nest!(|cx| cx.in_binder(&types))
1119 Closure(did, substs) => {
1120 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1121 p!(write("[closure"));
1123 // FIXME(eddyb) should use `def_span`.
1124 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1125 if cx.tcx.sess.opts.debugging_opts.span_free_formats {
1126 p!(write("@{:?}", hir_id));
1128 p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)));
1131 for (freevar, upvar_ty) in cx.tcx.freevars(did)
1133 .map_or(&[][..], |fv| &fv[..])
1140 cx.tcx.hir().name(freevar.var_id())),
1145 // cross-crate closure types should only be
1146 // visible in codegen bug reports, I imagine.
1147 p!(write("@{:?}", did));
1149 for (index, upvar_ty) in upvar_tys.enumerate() {
1151 write("{}{}:", sep, index),
1157 if cx.config.is_verbose {
1159 " closure_kind_ty={:?} closure_sig_ty={:?}",
1160 substs.closure_kind_ty(did, cx.tcx),
1161 substs.closure_sig_ty(did, cx.tcx)
1168 p!(write("["), print(ty), write("; "));
1170 ty::LazyConst::Unevaluated(_def_id, _substs) => {
1173 ty::LazyConst::Evaluated(c) => {
1175 ConstValue::Infer(..) => p!(write("_")),
1176 ConstValue::Param(ParamConst { name, .. }) =>
1177 p!(write("{}", name)),
1178 _ => p!(write("{}", c.unwrap_usize(cx.tcx))),
1185 p!(write("["), print(ty), write("]"))
1190 p!(print_display(self))
1196 ('tcx) ConstValue<'tcx>, (self, cx) {
1199 ConstValue::Infer(..) => p!(write("_")),
1200 ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
1201 _ => p!(write("{:?}", self)),
1208 ('tcx) ty::Const<'tcx>, (self, cx) {
1210 p!(write("{} : {}", self.val, self.ty))
1216 ('tcx) ty::LazyConst<'tcx>, (self, cx) {
1219 // FIXME(const_generics) this should print at least the type.
1220 ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
1221 ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
1228 () ty::ParamTy, (self, cx) {
1230 p!(write("{}", self.name))
1233 p!(write("{}/#{}", self.name, self.idx))
1239 () ty::ParamConst, (self, cx) {
1241 p!(write("{}", self.name))
1244 p!(write("{}/#{}", self.name, self.index))
1249 // Similar problem to `Binder<T>`, can't define a generic impl.
1250 define_print_multi! {
1252 ('tcx) ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
1253 ('tcx) ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
1257 p!(print(self.0), write(" : "), print(self.1))
1263 ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) {
1265 p!(print(self.a), write(" <: "), print(self.b))
1271 ('tcx) ty::TraitPredicate<'tcx>, (self, cx) {
1273 p!(write("TraitPredicate({:?})",
1277 p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1283 ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) {
1286 write("ProjectionPredicate("),
1287 print(self.projection_ty),
1293 p!(print(self.projection_ty), write(" == "), print(self.ty))
1299 ('tcx) ty::ProjectionTy<'tcx>, (self, cx) {
1301 nest!(|cx| cx.print_def_path(
1312 () ty::ClosureKind, (self, cx) {
1315 ty::ClosureKind::Fn => p!(write("Fn")),
1316 ty::ClosureKind::FnMut => p!(write("FnMut")),
1317 ty::ClosureKind::FnOnce => p!(write("FnOnce")),
1324 ('tcx) ty::Predicate<'tcx>, (self, cx) {
1327 ty::Predicate::Trait(ref data) => p!(print(data)),
1328 ty::Predicate::Subtype(ref predicate) => p!(print(predicate)),
1329 ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)),
1330 ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)),
1331 ty::Predicate::Projection(ref predicate) => p!(print(predicate)),
1332 ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
1333 ty::Predicate::ObjectSafe(trait_def_id) => {
1334 p!(write("the trait `"));
1335 nest!(|cx| cx.print_def_path(
1341 p!(write("` is object-safe"))
1343 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
1344 p!(write("the closure `"));
1345 nest!(|cx| cx.print_def_path(
1351 p!(write("` implements the trait `{}`", kind))
1353 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1354 p!(write("the constant `"));
1355 nest!(|cx| cx.print_def_path(
1361 p!(write("` can be evaluated"))
1367 ty::Predicate::Trait(ref a) => p!(print(a)),
1368 ty::Predicate::Subtype(ref pair) => p!(print(pair)),
1369 ty::Predicate::RegionOutlives(ref pair) => p!(print(pair)),
1370 ty::Predicate::TypeOutlives(ref pair) => p!(print(pair)),
1371 ty::Predicate::Projection(ref pair) => p!(print(pair)),
1372 ty::Predicate::WellFormed(ty) => p!(print(ty)),
1373 ty::Predicate::ObjectSafe(trait_def_id) => {
1374 p!(write("ObjectSafe({:?})", trait_def_id))
1376 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
1377 p!(write("ClosureKind({:?}, {:?}, {:?})",
1378 closure_def_id, closure_substs, kind))
1380 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1381 p!(write("ConstEvaluatable({:?}, {:?})", def_id, substs))
1389 ('tcx) Kind<'tcx>, (self, cx) {
1391 match self.unpack() {
1392 UnpackedKind::Lifetime(lt) => p!(print(lt)),
1393 UnpackedKind::Type(ty) => p!(print(ty)),
1394 UnpackedKind::Const(ct) => p!(print(ct)),
1398 match self.unpack() {
1399 UnpackedKind::Lifetime(lt) => p!(print(lt)),
1400 UnpackedKind::Type(ty) => p!(print(ty)),
1401 UnpackedKind::Const(ct) => p!(print(ct)),