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;
16 use std::fmt::{self, Write as _};
20 use rustc_target::spec::abi::Abi;
21 use syntax::ast::CRATE_NODE_ID;
22 use syntax::symbol::{Symbol, InternedString};
25 /// The "region highlights" are used to control region printing during
26 /// specific error messages. When a "region highlight" is enabled, it
27 /// gives an alternate way to print specific regions. For now, we
28 /// always print those regions using a number, so something like "`'0`".
30 /// Regions not selected by the region highlight mode are presently
32 #[derive(Copy, Clone, Default)]
33 pub struct RegionHighlightMode {
34 /// If enabled, when we see the selected region, use "`'N`"
35 /// instead of the ordinary behavior.
36 highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
38 /// If enabled, when printing a "free region" that originated from
39 /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
40 /// have names print as normal.
42 /// This is used when you have a signature like `fn foo(x: &u32,
43 /// y: &'a u32)` and we want to give a name to the region of the
45 highlight_bound_region: Option<(ty::BoundRegion, usize)>,
49 /// Mechanism for highlighting of specific regions for display in NLL region inference errors.
50 /// Contains region to highlight and counter for number to use when highlighting.
51 static REGION_HIGHLIGHT_MODE: Cell<RegionHighlightMode> =
52 Cell::new(RegionHighlightMode::default())
55 impl RegionHighlightMode {
56 /// Reads and returns the current region highlight settings (accesses thread-local state).
57 pub fn get() -> Self {
58 REGION_HIGHLIGHT_MODE.with(|c| c.get())
61 // Internal helper to update current settings during the execution of `op`.
65 op: impl FnOnce() -> R,
67 REGION_HIGHLIGHT_MODE.with(|c| {
75 /// If `region` and `number` are both `Some`, invokes
76 /// `highlighting_region`; otherwise, just invokes `op` directly.
77 pub fn maybe_highlighting_region<R>(
78 region: Option<ty::Region<'_>>,
79 number: Option<usize>,
80 op: impl FnOnce() -> R,
82 if let Some(k) = region {
83 if let Some(n) = number {
84 return Self::highlighting_region(k, n, op);
91 /// During the execution of `op`, highlights the region inference
92 /// variable `vid` as `'N`. We can only highlight one region `vid`
94 pub fn highlighting_region<R>(
95 region: ty::Region<'_>,
97 op: impl FnOnce() -> R,
99 let old_mode = Self::get();
100 let mut new_mode = old_mode;
101 let first_avail_slot = new_mode.highlight_regions.iter_mut()
102 .filter(|s| s.is_none())
106 "can only highlight {} placeholders at a time",
107 old_mode.highlight_regions.len(),
110 *first_avail_slot = Some((*region, number));
111 Self::set(old_mode, new_mode, op)
114 /// Convenience wrapper for `highlighting_region`.
115 pub fn highlighting_region_vid<R>(
118 op: impl FnOnce() -> R,
120 Self::highlighting_region(&ty::ReVar(vid), number, op)
123 /// Returns `Some(n)` with the number to use for the given region, if any.
124 fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
128 .filter_map(|h| match h {
129 Some((r, n)) if r == region => Some(*n),
135 /// During the execution of `op`, highlight the given bound
136 /// region. We can only highlight one bound region at a time. See
137 /// the field `highlight_bound_region` for more detailed notes.
138 pub fn highlighting_bound_region<R>(
141 op: impl FnOnce() -> R,
143 let old_mode = Self::get();
144 assert!(old_mode.highlight_bound_region.is_none());
148 highlight_bound_region: Some((br, number)),
155 /// Returns `Some(N)` if the placeholder `p` is highlighted to print as "`'N`".
156 pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> {
157 self.region_highlighted(&ty::RePlaceholder(p))
161 macro_rules! gen_display_debug_body {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| {
165 $with(&cx.tcx.lift(self).expect("could not lift for printing"), &mut cx)
170 macro_rules! gen_display_debug {
171 ( ($($x:tt)+) $target:ty, display yes ) => {
172 impl<$($x)+> fmt::Display for $target {
173 gen_display_debug_body! { Print::print_display }
176 ( () $target:ty, display yes ) => {
177 impl fmt::Display for $target {
178 gen_display_debug_body! { Print::print_display }
181 ( ($($x:tt)+) $target:ty, debug yes ) => {
182 impl<$($x)+> fmt::Debug for $target {
183 gen_display_debug_body! { Print::print_debug }
186 ( () $target:ty, debug yes ) => {
187 impl fmt::Debug for $target {
188 gen_display_debug_body! { Print::print_debug }
191 ( $generic:tt $target:ty, $t:ident no ) => {};
193 macro_rules! gen_print_impl {
194 ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
195 impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target {
197 type Error = fmt::Error;
198 fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result {
199 define_scoped_cx!($cx);
200 if $cx.config.is_debug $dbg
205 ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
206 impl<P: PrettyPrinter> Print<'tcx, P> for $target {
208 type Error = fmt::Error;
209 fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result {
210 define_scoped_cx!($cx);
211 if $cx.config.is_debug $dbg
216 ( $generic:tt $target:ty,
217 $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
218 gen_print_impl! { $generic $target, $vars $disp $dbg }
219 gen_display_debug! { $generic $target, display $gendisp }
220 gen_display_debug! { $generic $target, debug $gendbg }
223 macro_rules! define_print {
224 ( $generic:tt $target:ty,
225 $vars:tt { display $disp:block debug $dbg:block } ) => {
226 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
228 ( $generic:tt $target:ty,
229 $vars:tt { debug $dbg:block display $disp:block } ) => {
230 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
232 ( $generic:tt $target:ty,
233 $vars:tt { debug $dbg:block } ) => {
234 gen_print_impl! { $generic $target, $vars no {
235 bug!(concat!("display not implemented for ", stringify!($target)));
238 ( $generic:tt $target:ty,
239 ($self:ident, $cx:ident) { display $disp:block } ) => {
240 gen_print_impl! { $generic $target, ($self, $cx) yes $disp no {
241 write!($cx.printer, "{:?}", $self)
245 macro_rules! define_print_multi {
246 ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
247 $(define_print! { $generic $target, $vars $def })*
250 macro_rules! print_inner {
251 (write ($($data:expr),+)) => {
252 write!(scoped_cx!().printer, $($data),+)
254 ($kind:ident ($data:expr)) => {
255 $data.$kind(scoped_cx!())
259 ($($kind:ident $data:tt),+) => {
261 $(print_inner!($kind $data)?;)+
266 macro_rules! define_scoped_cx {
268 #[allow(unused_macros)]
269 macro_rules! scoped_cx {
275 impl<P: PrettyPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
282 define_scoped_cx!(self);
285 let mut inputs = inputs.iter();
286 if let Some(&ty) = inputs.next() {
287 p!(print_display(ty))?;
289 p!(write(", "), print_display(ty))?;
296 if !output.is_unit() {
297 p!(write(" -> "), print_display(output))?;
303 fn in_binder<T>(&mut self, value: &ty::Binder<T>) -> Result<T::Output, fmt::Error>
304 where T: Print<'tcx, P, Error = fmt::Error> + TypeFoldable<'tcx>
306 fn name_by_region_index(index: usize) -> InternedString {
308 0 => Symbol::intern("'r"),
309 1 => Symbol::intern("'s"),
310 i => Symbol::intern(&format!("'t{}", i-2)),
314 // Replace any anonymous late-bound regions with named
315 // variants, using gensym'd identifiers, so that we can
316 // clearly differentiate between named and unnamed regions in
317 // the output. We'll probably want to tweak this over time to
318 // decide just how much information to give.
319 if self.config.binder_depth == 0 {
320 self.prepare_late_bound_region_info(value);
323 let mut empty = true;
324 let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
325 define_scoped_cx!(cx);
329 p!(write("{}", start))
331 p!(write("{}", cont))
335 // NOTE(eddyb) this must be below `start_or_continue`'s definition
336 // as that also has a `define_scoped_cx` and that kind of shadowing
337 // is disallowed (name resolution thinks `scoped_cx!` is ambiguous).
338 define_scoped_cx!(self);
340 let old_region_index = self.config.region_index;
341 let mut region_index = old_region_index;
342 let new_value = self.tcx.replace_late_bound_regions(value, |br| {
343 let _ = start_or_continue(self, "for<", ", ");
345 ty::BrNamed(_, name) => {
346 let _ = p!(write("{}", name));
353 let name = name_by_region_index(region_index);
355 if !self.is_name_used(&name) {
359 let _ = p!(write("{}", name));
360 ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name)
363 self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
365 start_or_continue(self, "", "> ")?;
367 // Push current state to gcx, and restore after writing new_value.
368 self.config.binder_depth += 1;
369 self.config.region_index = region_index;
370 let result = new_value.print_display(self);
371 self.config.region_index = old_region_index;
372 self.config.binder_depth -= 1;
376 fn is_name_used(&self, name: &InternedString) -> bool {
377 match self.config.used_region_names {
378 Some(ref names) => names.contains(name),
384 pub fn parameterized<F: fmt::Write>(
387 substs: SubstsRef<'_>,
390 PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| {
391 let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
392 let _ = cx.print_def_path(did, Some(substs), ns, iter::empty())?;
398 ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, cx) {
400 // Generate the main trait ref, including associated types.
401 let mut first = true;
403 if let Some(principal) = self.principal() {
404 let mut resugared_principal = false;
406 // Special-case `Fn(...) -> ...` and resugar it.
407 let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id);
408 if !cx.config.is_verbose && fn_trait_kind.is_some() {
409 if let ty::Tuple(ref args) = principal.substs.type_at(0).sty {
410 let mut projections = self.projection_bounds();
411 if let (Some(proj), None) = (projections.next(), projections.next()) {
412 let _ = cx.print_def_path(
418 cx.fn_sig(args, false, proj.ty)?;
419 resugared_principal = true;
424 if !resugared_principal {
425 // Use a type that can't appear in defaults of type parameters.
426 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
427 let principal = principal.with_self_ty(cx.tcx, dummy_self);
428 let _ = cx.print_def_path(
430 Some(principal.substs),
432 self.projection_bounds(),
439 // FIXME(eddyb) avoid printing twice (needed to ensure
440 // that the auto traits are sorted *and* printed via cx).
441 let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
442 (cx.tcx.def_path_str(did), did)
445 // The auto traits come ordered by `DefPathHash`. While
446 // `DefPathHash` is *stable* in the sense that it depends on
447 // neither the host nor the phase of the moon, it depends
448 // "pseudorandomly" on the compiler version and the target.
450 // To avoid that causing instabilities in compiletest
451 // output, sort the auto-traits alphabetically.
454 for (_, def_id) in auto_traits {
460 let _ = cx.print_def_path(
473 impl fmt::Debug for ty::GenericParamDef {
474 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475 let type_name = match self.kind {
476 ty::GenericParamDefKind::Lifetime => "Lifetime",
477 ty::GenericParamDefKind::Type { .. } => "Type",
478 ty::GenericParamDefKind::Const => "Const",
480 write!(f, "{}({}, {:?}, {})",
488 impl fmt::Debug for ty::TraitDef {
489 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
490 PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| {
491 let _ = cx.print_def_path(
502 impl fmt::Debug for ty::AdtDef {
503 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
504 PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| {
505 let _ = cx.print_def_path(
516 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
517 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
518 write!(f, "ClosureUpvar({:?},{:?})",
524 impl fmt::Debug for ty::UpvarId {
525 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526 PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| {
527 define_scoped_cx!(cx);
528 p!(write("UpvarId({:?};`{}`;{:?})",
529 self.var_path.hir_id,
530 cx.tcx.hir().name_by_hir_id(self.var_path.hir_id),
531 self.closure_expr_id))
536 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
537 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
538 write!(f, "UpvarBorrow({:?}, {:?})",
539 self.kind, self.region)
544 ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, cx) {
547 let mut tys = self.iter();
548 if let Some(&ty) = tys.next() {
551 p!(write(", "), print(ty))?;
560 ('tcx) ty::TypeAndMut<'tcx>, (self, cx) {
563 write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
570 ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) {
572 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
574 ty::Binder::bind(*self)
575 .with_self_ty(cx.tcx, dummy_self)
580 self.print_display(cx)
586 ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) {
588 p!(write("{:?} -> ", self.kind), print(self.target))
594 () ty::BoundRegion, (self, cx) {
596 if cx.config.is_verbose {
597 return self.print_debug(cx);
600 if let BrNamed(_, name) = *self {
601 if name != "" && name != "'_" {
602 return p!(write("{}", name));
606 let highlight = RegionHighlightMode::get();
607 if let Some((region, counter)) = highlight.highlight_bound_region {
609 return p!(write("'{}", counter));
617 BrAnon(n) => p!(write("BrAnon({:?})", n)),
618 BrFresh(n) => p!(write("BrFresh({:?})", n)),
619 BrNamed(did, name) => {
620 p!(write("BrNamed({:?}:{:?}, {})",
621 did.krate, did.index, name))
623 BrEnv => p!(write("BrEnv")),
629 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
631 // NB: this must be kept in sync with the printing logic above.
632 impl ty::BoundRegion {
633 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
634 if cx.config.is_verbose {
638 if let BrNamed(_, name) = *self {
639 if name != "" && name != "'_" {
644 let highlight = RegionHighlightMode::get();
645 if let Some((region, _)) = highlight.highlight_bound_region {
656 () ty::PlaceholderRegion, (self, cx) {
658 if cx.config.is_verbose {
659 return self.print_debug(cx);
662 let highlight = RegionHighlightMode::get();
663 if let Some(counter) = highlight.placeholder_highlight(*self) {
664 return p!(write("'{}", counter));
667 p!(print_display(self.name))
672 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
674 // NB: this must be kept in sync with the printing logic above.
675 impl ty::PlaceholderRegion {
676 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
677 if cx.config.is_verbose {
681 let highlight = RegionHighlightMode::get();
682 if highlight.placeholder_highlight(*self).is_some() {
686 self.name.display_outputs_anything(cx)
691 () ty::RegionKind, (self, cx) {
693 if cx.config.is_verbose {
694 return self.print_debug(cx);
697 // Watch out for region highlights.
698 if let Some(n) = RegionHighlightMode::get().region_highlighted(self) {
699 return p!(write("'{:?}", n));
702 // These printouts are concise. They do not contain all the information
703 // the user might want to diagnose an error, but there is basically no way
704 // to fit that into a short string. Hence the recommendation to use
705 // `explain_region()` or `note_and_explain_region()`.
707 ty::ReEarlyBound(ref data) => {
708 if data.name != "'_" {
709 p!(write("{}", data.name))
714 ty::ReLateBound(_, br) |
715 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
716 p!(print_display(br))
718 ty::RePlaceholder(p) => {
721 ty::ReScope(scope) if cx.config.identify_regions => {
723 region::ScopeData::Node =>
724 p!(write("'{}s", scope.item_local_id().as_usize())),
725 region::ScopeData::CallSite =>
726 p!(write("'{}cs", scope.item_local_id().as_usize())),
727 region::ScopeData::Arguments =>
728 p!(write("'{}as", scope.item_local_id().as_usize())),
729 region::ScopeData::Destruction =>
730 p!(write("'{}ds", scope.item_local_id().as_usize())),
731 region::ScopeData::Remainder(first_statement_index) => p!(write(
733 scope.item_local_id().as_usize(),
734 first_statement_index.index()
738 ty::ReVar(region_vid) if cx.config.identify_regions => {
739 p!(print_debug(region_vid))
741 ty::ReVar(region_vid) => {
742 p!(print_display(region_vid))
745 ty::ReErased => Ok(()),
746 ty::ReStatic => p!(write("'static")),
747 ty::ReEmpty => p!(write("'<empty>")),
749 // The user should never encounter these in unsubstituted form.
750 ty::ReClosureBound(vid) => p!(write("{:?}", vid)),
755 ty::ReEarlyBound(ref data) => {
756 p!(write("ReEarlyBound({}, {})",
761 ty::ReClosureBound(ref vid) => {
762 p!(write("ReClosureBound({:?})",
766 ty::ReLateBound(binder_id, ref bound_region) => {
767 p!(write("ReLateBound({:?}, {:?})",
772 ty::ReFree(ref fr) => p!(write("{:?}", fr)),
775 p!(write("ReScope({:?})", id))
778 ty::ReStatic => p!(write("ReStatic")),
780 ty::ReVar(ref vid) => {
781 p!(write("{:?}", vid))
784 ty::RePlaceholder(placeholder) => {
785 p!(write("RePlaceholder({:?})", placeholder))
788 ty::ReEmpty => p!(write("ReEmpty")),
790 ty::ReErased => p!(write("ReErased"))
796 // HACK(eddyb) Trying to print a lifetime might not print anything, which
797 // may need special handling in the caller (of `ty::RegionKind::print`).
798 // To avoid printing to a temporary string, the `display_outputs_anything`
799 // method can instead be used to determine this, ahead of time.
801 // NB: this must be kept in sync with the printing logic above.
802 impl ty::RegionKind {
803 // HACK(eddyb) `pub(crate)` only for `ty::print`.
804 pub(crate) fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
805 if cx.config.is_verbose {
809 if RegionHighlightMode::get().region_highlighted(self).is_some() {
814 ty::ReEarlyBound(ref data) => {
815 data.name != "" && data.name != "'_"
818 ty::ReLateBound(_, br) |
819 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
820 br.display_outputs_anything(cx)
823 ty::RePlaceholder(p) => p.display_outputs_anything(cx),
826 ty::ReVar(_) if cx.config.identify_regions => true,
828 ty::ReVar(region_vid) => region_vid.display_outputs_anything(cx),
831 ty::ReErased => false,
835 ty::ReClosureBound(_) => true,
841 () ty::FreeRegion, (self, cx) {
843 p!(write("ReFree({:?}, {:?})", self.scope, self.bound_region))
849 () ty::Variance, (self, cx) {
851 cx.printer.write_str(match *self {
852 ty::Covariant => "+",
853 ty::Contravariant => "-",
854 ty::Invariant => "o",
855 ty::Bivariant => "*",
862 ('tcx) ty::FnSig<'tcx>, (self, cx) {
864 if self.unsafety == hir::Unsafety::Unsafe {
865 p!(write("unsafe "))?;
868 if self.abi != Abi::Rust {
869 p!(write("extern {} ", self.abi))?;
873 cx.fn_sig(self.inputs(), self.c_variadic, self.output())
876 p!(write("({:?}; c_variadic: {})->{:?}",
877 self.inputs(), self.c_variadic, self.output()))
882 impl fmt::Debug for ty::TyVid {
883 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
884 write!(f, "_#{}t", self.index)
888 impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
889 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
890 write!(f, "_#{}f", self.index)
894 impl fmt::Debug for ty::IntVid {
895 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
896 write!(f, "_#{}i", self.index)
900 impl fmt::Debug for ty::FloatVid {
901 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
902 write!(f, "_#{}f", self.index)
907 () ty::RegionVid, (self, cx) {
909 if cx.config.is_verbose {
910 return self.print_debug(cx);
913 let highlight = RegionHighlightMode::get();
914 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
915 return p!(write("'{:?}", counter));
921 // HACK(eddyb) this is duplicated from `display` printing,
922 // to keep NLL borrowck working even with `-Zverbose`.
923 let highlight = RegionHighlightMode::get();
924 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
925 return p!(write("'{:?}", counter));
928 p!(write("'_#{}r", self.index()))
933 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
935 // NB: this must be kept in sync with the printing logic above.
937 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
938 if cx.config.is_verbose {
942 let highlight = RegionHighlightMode::get();
943 if highlight.region_highlighted(&ty::ReVar(*self)).is_some() {
952 () ty::InferTy, (self, cx) {
954 if cx.config.is_verbose {
955 return self.print_debug(cx);
958 ty::TyVar(_) => p!(write("_")),
959 ty::IntVar(_) => p!(write("{}", "{integer}")),
960 ty::FloatVar(_) => p!(write("{}", "{float}")),
961 ty::FreshTy(v) => p!(write("FreshTy({})", v)),
962 ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)),
963 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v))
968 ty::TyVar(ref v) => p!(write("{:?}", v)),
969 ty::IntVar(ref v) => p!(write("{:?}", v)),
970 ty::FloatVar(ref v) => p!(write("{:?}", v)),
971 ty::FreshTy(v) => p!(write("FreshTy({:?})", v)),
972 ty::FreshIntTy(v) => p!(write("FreshIntTy({:?})", v)),
973 ty::FreshFloatTy(v) => p!(write("FreshFloatTy({:?})", v))
979 impl fmt::Debug for ty::IntVarValue {
980 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
982 ty::IntType(ref v) => v.fmt(f),
983 ty::UintType(ref v) => v.fmt(f),
988 impl fmt::Debug for ty::FloatVarValue {
989 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
994 // The generic impl doesn't work yet because projections are not
995 // normalized under HRTB.
996 /*impl<T> fmt::Display for ty::Binder<T>
997 where T: fmt::Display + for<'a> ty::Lift<'a>,
998 for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
1000 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1001 PrintCx::with_tls_tcx(|cx| cx.in_binder(cx.tcx.lift(self)
1002 .expect("could not lift for printing")))
1006 define_print_multi! {
1008 ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
1009 ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
1010 ('tcx) ty::Binder<ty::FnSig<'tcx>>,
1011 ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
1012 ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
1013 ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
1014 ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
1015 ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
1025 ('tcx) ty::TraitRef<'tcx>, (self, cx) {
1027 let _ = cx.print_def_path(
1036 let _ = cx.path_qualified(None, self.self_ty(), Some(*self), Namespace::TypeNS)?;
1043 ('tcx) ty::Ty<'tcx>, (self, cx) {
1046 Bool => p!(write("bool")),
1047 Char => p!(write("char")),
1048 Int(t) => p!(write("{}", t.ty_to_string())),
1049 Uint(t) => p!(write("{}", t.ty_to_string())),
1050 Float(t) => p!(write("{}", t.ty_to_string())),
1052 p!(write("*{} ", match tm.mutbl {
1053 hir::MutMutable => "mut",
1054 hir::MutImmutable => "const",
1058 Ref(r, ty, mutbl) => {
1060 if r.display_outputs_anything(cx) {
1061 p!(print_display(r), write(" "))?;
1063 ty::TypeAndMut { ty, mutbl }.print(cx)
1065 Never => p!(write("!")),
1068 let mut tys = tys.iter();
1069 if let Some(&ty) = tys.next() {
1070 p!(print(ty), write(","))?;
1071 if let Some(&ty) = tys.next() {
1072 p!(write(" "), print(ty))?;
1074 p!(write(", "), print(ty))?;
1080 FnDef(def_id, substs) => {
1081 let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs);
1082 p!(print(sig), write(" {{"))?;
1083 let _ = cx.print_def_path(
1091 FnPtr(ref bare_fn) => {
1094 Infer(infer_ty) => p!(write("{}", infer_ty)),
1095 Error => p!(write("[type error]")),
1096 Param(ref param_ty) => p!(write("{}", param_ty)),
1097 Bound(debruijn, bound_ty) => {
1098 match bound_ty.kind {
1099 ty::BoundTyKind::Anon => {
1100 if debruijn == ty::INNERMOST {
1101 p!(write("^{}", bound_ty.var.index()))
1103 p!(write("^{}_{}", debruijn.index(), bound_ty.var.index()))
1107 ty::BoundTyKind::Param(p) => p!(write("{}", p)),
1110 Adt(def, substs) => {
1111 let _ = cx.print_def_path(
1119 Dynamic(data, r) => {
1120 let print_r = r.display_outputs_anything(cx);
1127 p!(write(" + "), print_display(r), write(")"))?;
1131 Foreign(def_id) => {
1132 let _ = cx.print_def_path(
1140 Projection(ref data) => data.print(cx),
1141 UnnormalizedProjection(ref data) => {
1142 p!(write("Unnormalized("))?;
1146 Placeholder(placeholder) => {
1147 p!(write("Placeholder({:?})", placeholder))
1149 Opaque(def_id, substs) => {
1150 if cx.config.is_verbose {
1151 return p!(write("Opaque({:?}, {:?})", def_id, substs));
1154 let def_key = cx.tcx.def_key(def_id);
1155 if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
1156 p!(write("{}", name))?;
1157 let mut substs = substs.iter();
1158 // FIXME(eddyb) print this with `print_def_path`.
1159 if let Some(first) = substs.next() {
1161 p!(write("{}", first))?;
1162 for subst in substs {
1163 p!(write(", {}", subst))?;
1169 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1170 // by looking up the projections associated with the def_id.
1171 let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs);
1173 let mut first = true;
1174 let mut is_sized = false;
1176 for predicate in bounds.predicates {
1177 if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
1178 // Don't print +Sized, but rather +?Sized if absent.
1179 if Some(trait_ref.def_id()) == cx.tcx.lang_items().sized_trait() {
1185 write("{}", if first { " " } else { "+" }),
1191 p!(write("{}?Sized", if first { " " } else { "+" }))?;
1193 p!(write(" Sized"))?;
1197 Str => p!(write("str")),
1198 Generator(did, substs, movability) => {
1199 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1200 let witness = substs.witness(did, cx.tcx);
1201 if movability == hir::GeneratorMovability::Movable {
1202 p!(write("[generator"))?;
1204 p!(write("[static generator"))?;
1207 // FIXME(eddyb) should use `def_span`.
1208 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1209 p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?;
1211 cx.tcx.with_freevars(hir_id, |freevars| {
1212 for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1216 cx.tcx.hir().name(freevar.var_id())),
1223 // cross-crate closure types should only be
1224 // visible in codegen bug reports, I imagine.
1225 p!(write("@{:?}", did))?;
1227 for (index, upvar_ty) in upvar_tys.enumerate() {
1229 write("{}{}:", sep, index),
1235 p!(write(" "), print(witness), write("]"))
1237 GeneratorWitness(types) => {
1238 cx.in_binder(&types)
1240 Closure(did, substs) => {
1241 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1242 p!(write("[closure"))?;
1244 // FIXME(eddyb) should use `def_span`.
1245 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1246 if cx.tcx.sess.opts.debugging_opts.span_free_formats {
1247 p!(write("@{:?}", hir_id))?;
1249 p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?;
1252 cx.tcx.with_freevars(hir_id, |freevars| {
1253 for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1257 cx.tcx.hir().name(freevar.var_id())),
1264 // cross-crate closure types should only be
1265 // visible in codegen bug reports, I imagine.
1266 p!(write("@{:?}", did))?;
1268 for (index, upvar_ty) in upvar_tys.enumerate() {
1270 write("{}{}:", sep, index),
1278 " closure_kind_ty={:?} closure_sig_ty={:?}",
1279 substs.closure_kind_ty(did, cx.tcx),
1280 substs.closure_sig_ty(did, cx.tcx)
1287 p!(write("["), print(ty), write("; "))?;
1289 ty::LazyConst::Unevaluated(_def_id, _substs) => {
1292 ty::LazyConst::Evaluated(c) => {
1294 ConstValue::Infer(..) => p!(write("_"))?,
1295 ConstValue::Param(ParamConst { name, .. }) =>
1296 p!(write("{}", name))?,
1297 _ => p!(write("{}", c.unwrap_usize(cx.tcx)))?,
1304 p!(write("["), print(ty), write("]"))
1309 self.print_display(cx)
1315 ('tcx) ConstValue<'tcx>, (self, cx) {
1318 ConstValue::Infer(..) => p!(write("_")),
1319 ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
1320 _ => p!(write("{:?}", self)),
1327 ('tcx) ty::Const<'tcx>, (self, cx) {
1329 p!(write("{} : {}", self.val, self.ty))
1335 ('tcx) ty::LazyConst<'tcx>, (self, cx) {
1338 // FIXME(const_generics) this should print at least the type.
1339 ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
1340 ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
1347 () ty::ParamTy, (self, cx) {
1349 p!(write("{}", self.name))
1352 p!(write("{}/#{}", self.name, self.idx))
1358 () ty::ParamConst, (self, cx) {
1360 p!(write("{}", self.name))
1363 p!(write("{}/#{}", self.name, self.index))
1368 // Similar problem to `Binder<T>`, can't define a generic impl.
1369 define_print_multi! {
1371 ('tcx) ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
1372 ('tcx) ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
1376 p!(print(self.0), write(" : "), print(self.1))
1382 ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) {
1384 p!(print(self.a), write(" <: "), print(self.b))
1390 ('tcx) ty::TraitPredicate<'tcx>, (self, cx) {
1392 p!(write("TraitPredicate({:?})",
1396 p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1402 ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) {
1405 write("ProjectionPredicate("),
1406 print(self.projection_ty),
1412 p!(print(self.projection_ty), write(" == "), print(self.ty))
1418 ('tcx) ty::ProjectionTy<'tcx>, (self, cx) {
1420 let _ = cx.print_def_path(
1432 () ty::ClosureKind, (self, cx) {
1435 ty::ClosureKind::Fn => p!(write("Fn")),
1436 ty::ClosureKind::FnMut => p!(write("FnMut")),
1437 ty::ClosureKind::FnOnce => p!(write("FnOnce")),
1444 ('tcx) ty::Predicate<'tcx>, (self, cx) {
1447 ty::Predicate::Trait(ref data) => data.print(cx),
1448 ty::Predicate::Subtype(ref predicate) => predicate.print(cx),
1449 ty::Predicate::RegionOutlives(ref predicate) => predicate.print(cx),
1450 ty::Predicate::TypeOutlives(ref predicate) => predicate.print(cx),
1451 ty::Predicate::Projection(ref predicate) => predicate.print(cx),
1452 ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")),
1453 ty::Predicate::ObjectSafe(trait_def_id) => {
1454 p!(write("the trait `"))?;
1455 let _ = cx.print_def_path(
1461 p!(write("` is object-safe"))
1463 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
1464 p!(write("the closure `"))?;
1465 let _ = cx.print_def_path(
1471 p!(write("` implements the trait `{}`", kind))
1473 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1474 p!(write("the constant `"))?;
1475 let _ = cx.print_def_path(
1481 p!(write("` can be evaluated"))
1487 ty::Predicate::Trait(ref a) => a.print(cx),
1488 ty::Predicate::Subtype(ref pair) => pair.print(cx),
1489 ty::Predicate::RegionOutlives(ref pair) => pair.print(cx),
1490 ty::Predicate::TypeOutlives(ref pair) => pair.print(cx),
1491 ty::Predicate::Projection(ref pair) => pair.print(cx),
1492 ty::Predicate::WellFormed(ty) => ty.print(cx),
1493 ty::Predicate::ObjectSafe(trait_def_id) => {
1494 p!(write("ObjectSafe({:?})", trait_def_id))
1496 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
1497 p!(write("ClosureKind({:?}, {:?}, {:?})",
1498 closure_def_id, closure_substs, kind))
1500 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1501 p!(write("ConstEvaluatable({:?}, {:?})", def_id, substs))
1509 ('tcx) Kind<'tcx>, (self, cx) {
1511 match self.unpack() {
1512 UnpackedKind::Lifetime(lt) => p!(print(lt)),
1513 UnpackedKind::Type(ty) => p!(print(ty)),
1514 UnpackedKind::Const(ct) => p!(print(ct)),
1518 match self.unpack() {
1519 UnpackedKind::Lifetime(lt) => p!(print(lt)),
1520 UnpackedKind::Type(ty) => p!(print(ty)),
1521 UnpackedKind::Const(ct) => p!(print(ct)),