1 use crate::hir::def_id::DefId;
2 use crate::hir::map::definitions::DefPathData;
3 use crate::middle::region;
4 use crate::ty::subst::{self, 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::{PrintCx, Print};
13 use crate::mir::interpret::ConstValue;
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(|mut cx| {
165 $with(&cx.tcx.lift(self).expect("could not lift for printing"), f, &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, $f:ident, $cx:ident) $disp:block $dbg:block ) => {
195 impl<$($x)+> Print<'tcx> for $target {
196 fn print<F: fmt::Write>(
199 $cx: &mut PrintCx<'_, '_, 'tcx>,
206 ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => {
207 impl Print<'tcx> for $target {
208 fn print<F: fmt::Write>(
211 $cx: &mut PrintCx<'_, '_, 'tcx>,
218 ( $generic:tt $target:ty,
219 $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
220 gen_print_impl! { $generic $target, $vars $disp $dbg }
221 gen_display_debug! { $generic $target, display $gendisp }
222 gen_display_debug! { $generic $target, debug $gendbg }
225 macro_rules! define_print {
226 ( $generic:tt $target:ty,
227 $vars:tt { display $disp:block debug $dbg:block } ) => {
228 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
230 ( $generic:tt $target:ty,
231 $vars:tt { debug $dbg:block display $disp:block } ) => {
232 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
234 ( $generic:tt $target:ty,
235 $vars:tt { debug $dbg:block } ) => {
236 gen_print_impl! { $generic $target, $vars no {
237 bug!(concat!("display not implemented for ", stringify!($target)));
240 ( $generic:tt $target:ty,
241 ($self:ident, $f:ident, $cx:ident) { display $disp:block } ) => {
242 gen_print_impl! { $generic $target, ($self, $f, $cx) yes $disp no {
243 write!($f, "{:?}", $self)
247 macro_rules! define_print_multi {
248 ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
249 $(define_print! { $generic $target, $vars $def })*
252 macro_rules! print_inner {
253 ( $f:expr, $cx:expr, write ($($data:expr),+) ) => {
254 write!($f, $($data),+)
256 ( $f:expr, $cx:expr, $kind:ident ($data:expr) ) => {
261 ( $f:expr, $cx:expr $(, $kind:ident $data:tt)+ ) => {
262 Ok(())$(.and_then(|_| print_inner!($f, $cx, $kind $data)))+
266 impl PrintCx<'a, 'gcx, 'tcx> {
267 fn fn_sig<F: fmt::Write>(&mut self,
274 let mut inputs = inputs.iter();
275 if let Some(&ty) = inputs.next() {
276 print!(f, self, print_display(ty))?;
278 print!(f, self, write(", "), print_display(ty))?;
285 if !output.is_unit() {
286 print!(f, self, write(" -> "), print_display(output))?;
292 fn parameterized<F: fmt::Write>(
296 substs: SubstsRef<'tcx>,
297 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
299 let mut key = self.tcx.def_key(def_id);
300 let is_value_ns = match key.disambiguated_data.data {
301 DefPathData::ValueNs(_) |
302 DefPathData::EnumVariant(_) => true,
304 // Skip `StructCtor` so that `Struct::<T>` will be printed,
305 // instead of the less pretty `Struct<T>::{{constructor}}`.
306 DefPathData::StructCtor => {
307 def_id.index = key.parent.unwrap();
308 key = self.tcx.def_key(def_id);
315 let generics = self.tcx.generics_of(def_id);
317 if let Some(parent_def_id) = generics.parent {
318 assert_eq!(parent_def_id, DefId { index: key.parent.unwrap(), ..def_id });
320 let parent_generics = self.tcx.generics_of(parent_def_id);
321 let parent_has_own_self =
322 parent_generics.has_self && parent_generics.parent_count == 0;
323 if parent_has_own_self {
324 print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
326 self.parameterized(f, parent_def_id, substs, iter::empty())?;
327 if parent_has_own_self {
331 write!(f, "::{}", key.disambiguated_data.data.as_interned_str())?;
333 // Try to print `impl`s more like how you'd refer to their associated items.
334 if let DefPathData::Impl = key.disambiguated_data.data {
335 if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
336 // HACK(eddyb) this is in lieu of more specific disambiguation.
337 print!(f, self, write("{}", self.tcx.item_path_str(def_id)))?;
339 let trait_ref = trait_ref.subst(self.tcx, substs);
340 print!(f, self, print_debug(trait_ref))?;
342 let self_ty = self.tcx.type_of(def_id).subst(self.tcx, substs);
343 // FIXME(eddyb) omit the <> where possible.
344 print!(f, self, write("<"), print(self_ty), write(">"))?;
349 print!(f, self, write("{}", self.tcx.item_path_str(def_id)))?;
352 let mut empty = true;
353 let mut start_or_continue = |f: &mut F, start: &str, cont: &str| {
356 write!(f, "{}", start)
358 write!(f, "{}", cont)
362 let start = if is_value_ns { "::<" } else { "<" };
364 let has_own_self = generics.has_self && generics.parent_count == 0;
365 let params = &generics.params[has_own_self as usize..];
367 // Don't print any regions if they're all erased.
368 let print_regions = params.iter().any(|param| {
369 match substs[param.index as usize].unpack() {
370 UnpackedKind::Lifetime(r) => *r != ty::ReErased,
375 // Don't print args that are the defaults of their respective parameters.
376 let num_supplied_defaults = if self.is_verbose {
379 params.iter().rev().take_while(|param| {
381 ty::GenericParamDefKind::Lifetime => false,
382 ty::GenericParamDefKind::Type { has_default, .. } => {
383 has_default && substs[param.index as usize] == Kind::from(
384 self.tcx.type_of(param.def_id).subst(self.tcx, substs)
387 ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
392 for param in ¶ms[..params.len() - num_supplied_defaults] {
393 match substs[param.index as usize].unpack() {
394 UnpackedKind::Lifetime(region) => {
398 start_or_continue(f, start, ", ")?;
399 if !region.display_outputs_anything(self) {
400 // This happens when the value of the region
401 // parameter is not easily serialized. This may be
402 // because the user omitted it in the first place,
403 // or because it refers to some block in the code,
404 // etc. I'm not sure how best to serialize this.
407 region.print_display(f, self)?;
410 UnpackedKind::Type(ty) => {
411 start_or_continue(f, start, ", ")?;
412 ty.print_display(f, self)?;
414 UnpackedKind::Const(ct) => {
415 start_or_continue(f, start, ", ")?;
416 ct.print_display(f, self)?;
421 for projection in projections {
422 start_or_continue(f, start, ", ")?;
425 self.tcx.associated_item(projection.item_def_id).ident),
426 print_display(projection.ty))?;
429 start_or_continue(f, "", ">")
432 fn in_binder<T, F>(&mut self, f: &mut F, value: &ty::Binder<T>) -> fmt::Result
433 where T: Print<'tcx> + TypeFoldable<'tcx>, F: fmt::Write
435 fn name_by_region_index(index: usize) -> InternedString {
437 0 => Symbol::intern("'r"),
438 1 => Symbol::intern("'s"),
439 i => Symbol::intern(&format!("'t{}", i-2)),
443 // Replace any anonymous late-bound regions with named
444 // variants, using gensym'd identifiers, so that we can
445 // clearly differentiate between named and unnamed regions in
446 // the output. We'll probably want to tweak this over time to
447 // decide just how much information to give.
448 if self.binder_depth == 0 {
449 self.prepare_late_bound_region_info(value);
452 let mut empty = true;
453 let mut start_or_continue = |f: &mut F, start: &str, cont: &str| {
456 write!(f, "{}", start)
458 write!(f, "{}", cont)
462 let old_region_index = self.region_index;
463 let mut region_index = old_region_index;
464 let new_value = self.tcx.replace_late_bound_regions(value, |br| {
465 let _ = start_or_continue(f, "for<", ", ");
467 ty::BrNamed(_, name) => {
468 let _ = write!(f, "{}", name);
475 let name = name_by_region_index(region_index);
477 if !self.is_name_used(&name) {
481 let _ = write!(f, "{}", name);
482 ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name)
485 self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
487 start_or_continue(f, "", "> ")?;
489 // Push current state to gcx, and restore after writing new_value.
490 self.binder_depth += 1;
491 self.region_index = region_index;
492 let result = new_value.print_display(f, self);
493 self.region_index = old_region_index;
494 self.binder_depth -= 1;
498 fn is_name_used(&self, name: &InternedString) -> bool {
499 match self.used_region_names {
500 Some(ref names) => names.contains(name),
506 pub fn parameterized<F: fmt::Write>(f: &mut F, did: DefId, substs: SubstsRef<'_>) -> fmt::Result {
507 PrintCx::with(|mut cx| {
508 let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
509 cx.parameterized(f, did, substs, iter::empty())
513 impl<'a, 'tcx, T: Print<'tcx>> Print<'tcx> for &'a T {
514 fn print<F: fmt::Write>(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result {
520 ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, f, cx) {
522 // Generate the main trait ref, including associated types.
523 let mut first = true;
525 if let Some(principal) = self.principal() {
526 let mut resugared_principal = false;
528 // Special-case `Fn(...) -> ...` and resugar it.
529 if !cx.is_verbose && cx.tcx.lang_items().fn_trait_kind(principal.def_id).is_some() {
530 if let Tuple(ref args) = principal.substs.type_at(0).sty {
531 let mut projections = self.projection_bounds();
532 if let (Some(proj), None) = (projections.next(), projections.next()) {
533 print!(f, cx, write("{}", cx.tcx.item_path_str(principal.def_id)))?;
534 cx.fn_sig(f, args, false, proj.ty)?;
535 resugared_principal = true;
540 if !resugared_principal {
541 // Use a type that can't appear in defaults of type parameters.
542 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
543 let principal = principal.with_self_ty(cx.tcx, dummy_self);
548 self.projection_bounds(),
555 let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
556 cx.tcx.item_path_str(did)
559 // The auto traits come ordered by `DefPathHash`. While
560 // `DefPathHash` is *stable* in the sense that it depends on
561 // neither the host nor the phase of the moon, it depends
562 // "pseudorandomly" on the compiler version and the target.
564 // To avoid that causing instabilities in compiletest
565 // output, sort the auto-traits alphabetically.
568 for auto_trait in auto_traits {
574 write!(f, "{}", auto_trait)?;
582 impl fmt::Debug for ty::GenericParamDef {
583 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584 let type_name = match self.kind {
585 ty::GenericParamDefKind::Lifetime => "Lifetime",
586 ty::GenericParamDefKind::Type { .. } => "Type",
587 ty::GenericParamDefKind::Const => "Const",
589 write!(f, "{}({}, {:?}, {})",
597 impl fmt::Debug for ty::TraitDef {
598 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600 write!(f, "{}", cx.tcx.item_path_str(self.def_id))
605 impl fmt::Debug for ty::AdtDef {
606 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
608 write!(f, "{}", cx.tcx.item_path_str(self.did))
613 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
614 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
615 write!(f, "ClosureUpvar({:?},{:?})",
621 impl fmt::Debug for ty::UpvarId {
622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
623 write!(f, "UpvarId({:?};`{}`;{:?})",
624 self.var_path.hir_id,
626 cx.tcx.hir().name_by_hir_id(self.var_path.hir_id)
628 self.closure_expr_id)
632 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
633 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
634 write!(f, "UpvarBorrow({:?}, {:?})",
635 self.kind, self.region)
640 ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, f, cx) {
643 let mut tys = self.iter();
644 if let Some(&ty) = tys.next() {
645 print!(f, cx, print(ty))?;
647 print!(f, cx, write(", "), print(ty))?;
656 ('tcx) ty::TypeAndMut<'tcx>, (self, f, cx) {
659 write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
666 ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) {
668 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
670 let trait_ref = *ty::Binder::bind(*self)
671 .with_self_ty(cx.tcx, dummy_self)
673 cx.parameterized(f, trait_ref.def_id, trait_ref.substs, iter::empty())
676 self.print_display(f, cx)
682 ('tcx) ty::adjustment::Adjustment<'tcx>, (self, f, cx) {
684 print!(f, cx, write("{:?} -> ", self.kind), print(self.target))
690 () ty::BoundRegion, (self, f, cx) {
693 return self.print_debug(f, cx);
696 if let BrNamed(_, name) = *self {
697 if name != "" && name != "'_" {
698 return write!(f, "{}", name);
702 let highlight = RegionHighlightMode::get();
703 if let Some((region, counter)) = highlight.highlight_bound_region {
705 return write!(f, "'{}", counter);
713 BrAnon(n) => write!(f, "BrAnon({:?})", n),
714 BrFresh(n) => write!(f, "BrFresh({:?})", n),
715 BrNamed(did, name) => {
716 write!(f, "BrNamed({:?}:{:?}, {})",
717 did.krate, did.index, name)
719 BrEnv => write!(f, "BrEnv"),
725 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
727 // NB: this must be kept in sync with the printing logic above.
728 impl ty::BoundRegion {
729 fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool {
734 if let BrNamed(_, name) = *self {
735 if name != "" && name != "'_" {
740 let highlight = RegionHighlightMode::get();
741 if let Some((region, _)) = highlight.highlight_bound_region {
752 () ty::PlaceholderRegion, (self, f, cx) {
755 return self.print_debug(f, cx);
758 let highlight = RegionHighlightMode::get();
759 if let Some(counter) = highlight.placeholder_highlight(*self) {
760 return write!(f, "'{}", counter);
763 write!(f, "{}", self.name)
768 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
770 // NB: this must be kept in sync with the printing logic above.
771 impl ty::PlaceholderRegion {
772 fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool {
777 let highlight = RegionHighlightMode::get();
778 if highlight.placeholder_highlight(*self).is_some() {
782 self.name.display_outputs_anything(cx)
787 () ty::RegionKind, (self, f, cx) {
790 return self.print_debug(f, cx);
793 // Watch out for region highlights.
794 if let Some(n) = RegionHighlightMode::get().region_highlighted(self) {
795 return write!(f, "'{:?}", n);
798 // These printouts are concise. They do not contain all the information
799 // the user might want to diagnose an error, but there is basically no way
800 // to fit that into a short string. Hence the recommendation to use
801 // `explain_region()` or `note_and_explain_region()`.
803 ty::ReEarlyBound(ref data) => {
804 if data.name != "'_" {
805 write!(f, "{}", data.name)
810 ty::ReLateBound(_, br) |
811 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
814 ty::RePlaceholder(p) => {
817 ty::ReScope(scope) if cx.identify_regions => {
819 region::ScopeData::Node =>
820 write!(f, "'{}s", scope.item_local_id().as_usize()),
821 region::ScopeData::CallSite =>
822 write!(f, "'{}cs", scope.item_local_id().as_usize()),
823 region::ScopeData::Arguments =>
824 write!(f, "'{}as", scope.item_local_id().as_usize()),
825 region::ScopeData::Destruction =>
826 write!(f, "'{}ds", scope.item_local_id().as_usize()),
827 region::ScopeData::Remainder(first_statement_index) => write!(
830 scope.item_local_id().as_usize(),
831 first_statement_index.index()
835 ty::ReVar(region_vid) if cx.identify_regions => {
836 write!(f, "{:?}", region_vid)
838 ty::ReVar(region_vid) => {
839 write!(f, "{}", region_vid)
842 ty::ReErased => Ok(()),
843 ty::ReStatic => write!(f, "'static"),
844 ty::ReEmpty => write!(f, "'<empty>"),
846 // The user should never encounter these in unsubstituted form.
847 ty::ReClosureBound(vid) => write!(f, "{:?}", vid),
852 ty::ReEarlyBound(ref data) => {
853 write!(f, "ReEarlyBound({}, {})",
858 ty::ReClosureBound(ref vid) => {
859 write!(f, "ReClosureBound({:?})",
863 ty::ReLateBound(binder_id, ref bound_region) => {
864 write!(f, "ReLateBound({:?}, {:?})",
869 ty::ReFree(ref fr) => write!(f, "{:?}", fr),
872 write!(f, "ReScope({:?})", id)
875 ty::ReStatic => write!(f, "ReStatic"),
877 ty::ReVar(ref vid) => {
878 write!(f, "{:?}", vid)
881 ty::RePlaceholder(placeholder) => {
882 write!(f, "RePlaceholder({:?})", placeholder)
885 ty::ReEmpty => write!(f, "ReEmpty"),
887 ty::ReErased => write!(f, "ReErased")
893 // HACK(eddyb) Trying to print a lifetime might not print anything, which
894 // may need special handling in the caller (of `ty::RegionKind::print`).
895 // To avoid printing to a temporary string, the `display_outputs_anything`
896 // method can instead be used to determine this, ahead of time.
898 // NB: this must be kept in sync with the printing logic above.
899 impl ty::RegionKind {
900 fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool {
905 if RegionHighlightMode::get().region_highlighted(self).is_some() {
910 ty::ReEarlyBound(ref data) => {
911 data.name != "" && data.name != "'_"
914 ty::ReLateBound(_, br) |
915 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
916 br.display_outputs_anything(cx)
919 ty::RePlaceholder(p) => p.display_outputs_anything(cx),
922 ty::ReVar(_) if cx.identify_regions => true,
924 ty::ReVar(region_vid) => region_vid.display_outputs_anything(cx),
927 ty::ReErased => false,
931 ty::ReClosureBound(_) => true,
937 () ty::FreeRegion, (self, f, cx) {
939 write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region)
945 () ty::Variance, (self, f, cx) {
947 f.write_str(match *self {
948 ty::Covariant => "+",
949 ty::Contravariant => "-",
950 ty::Invariant => "o",
951 ty::Bivariant => "*",
958 ('tcx) ty::FnSig<'tcx>, (self, f, cx) {
960 if self.unsafety == hir::Unsafety::Unsafe {
961 write!(f, "unsafe ")?;
964 if self.abi != Abi::Rust {
965 write!(f, "extern {} ", self.abi)?;
969 cx.fn_sig(f, self.inputs(), self.c_variadic, self.output())
972 write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())
977 impl fmt::Debug for ty::TyVid {
978 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
979 write!(f, "_#{}t", self.index)
983 impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
984 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
985 write!(f, "_#{}f", self.index)
989 impl fmt::Debug for ty::IntVid {
990 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
991 write!(f, "_#{}i", self.index)
995 impl fmt::Debug for ty::FloatVid {
996 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
997 write!(f, "_#{}f", self.index)
1002 () ty::RegionVid, (self, f, cx) {
1005 return self.print_debug(f, cx);
1008 let highlight = RegionHighlightMode::get();
1009 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
1010 return write!(f, "'{:?}", counter);
1016 // HACK(eddyb) this is duplicated from `display` printing,
1017 // to keep NLL borrowck working even with `-Zverbose`.
1018 let highlight = RegionHighlightMode::get();
1019 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
1020 return write!(f, "'{:?}", counter);
1023 write!(f, "'_#{}r", self.index())
1028 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
1030 // NB: this must be kept in sync with the printing logic above.
1031 impl ty::RegionVid {
1032 fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool {
1037 let highlight = RegionHighlightMode::get();
1038 if highlight.region_highlighted(&ty::ReVar(*self)).is_some() {
1047 () ty::InferTy, (self, f, cx) {
1050 return self.print_debug(f, cx);
1053 ty::TyVar(_) => write!(f, "_"),
1054 ty::IntVar(_) => write!(f, "{}", "{integer}"),
1055 ty::FloatVar(_) => write!(f, "{}", "{float}"),
1056 ty::FreshTy(v) => write!(f, "FreshTy({})", v),
1057 ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v),
1058 ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v)
1063 ty::TyVar(ref v) => write!(f, "{:?}", v),
1064 ty::IntVar(ref v) => write!(f, "{:?}", v),
1065 ty::FloatVar(ref v) => write!(f, "{:?}", v),
1066 ty::FreshTy(v) => write!(f, "FreshTy({:?})", v),
1067 ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v),
1068 ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v)
1074 impl fmt::Debug for ty::IntVarValue {
1075 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1077 ty::IntType(ref v) => v.fmt(f),
1078 ty::UintType(ref v) => v.fmt(f),
1083 impl fmt::Debug for ty::FloatVarValue {
1084 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1089 // The generic impl doesn't work yet because projections are not
1090 // normalized under HRTB.
1091 /*impl<T> fmt::Display for ty::Binder<T>
1092 where T: fmt::Display + for<'a> ty::Lift<'a>,
1093 for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
1095 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1096 PrintCx::with(|cx| cx.in_binder(f, cx.tcx.lift(self)
1097 .expect("could not lift for printing")))
1101 define_print_multi! {
1103 ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
1104 ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
1105 ('tcx) ty::Binder<ty::FnSig<'tcx>>,
1106 ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
1107 ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
1108 ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
1109 ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
1110 ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
1114 cx.in_binder(f, self)
1120 ('tcx) ty::TraitRef<'tcx>, (self, f, cx) {
1122 cx.parameterized(f, self.def_id, self.substs, iter::empty())
1125 // when printing out the debug representation, we don't need
1126 // to enumerate the `for<...>` etc because the debruijn index
1127 // tells you everything you need to know.
1130 print(self.self_ty()),
1132 cx.parameterized(f, self.def_id, self.substs, iter::empty())?;
1139 ('tcx) ty::Ty<'tcx>, (self, f, cx) {
1142 Bool => write!(f, "bool"),
1143 Char => write!(f, "char"),
1144 Int(t) => write!(f, "{}", t.ty_to_string()),
1145 Uint(t) => write!(f, "{}", t.ty_to_string()),
1146 Float(t) => write!(f, "{}", t.ty_to_string()),
1148 write!(f, "*{} ", match tm.mutbl {
1149 hir::MutMutable => "mut",
1150 hir::MutImmutable => "const",
1154 Ref(r, ty, mutbl) => {
1156 if r.display_outputs_anything(cx) {
1157 print!(f, cx, print_display(r), write(" "))?;
1159 ty::TypeAndMut { ty, mutbl }.print(f, cx)
1161 Never => write!(f, "!"),
1164 let mut tys = tys.iter();
1165 if let Some(&ty) = tys.next() {
1166 print!(f, cx, print(ty), write(","))?;
1167 if let Some(&ty) = tys.next() {
1168 print!(f, cx, write(" "), print(ty))?;
1170 print!(f, cx, write(", "), print(ty))?;
1176 FnDef(def_id, substs) => {
1177 let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs);
1178 print!(f, cx, print(sig), write(" {{"))?;
1179 cx.parameterized(f, def_id, substs, iter::empty())?;
1182 FnPtr(ref bare_fn) => {
1183 bare_fn.print(f, cx)
1185 Infer(infer_ty) => write!(f, "{}", infer_ty),
1186 Error => write!(f, "[type error]"),
1187 Param(ref param_ty) => write!(f, "{}", param_ty),
1188 Bound(debruijn, bound_ty) => {
1189 match bound_ty.kind {
1190 ty::BoundTyKind::Anon => {
1191 if debruijn == ty::INNERMOST {
1192 write!(f, "^{}", bound_ty.var.index())
1194 write!(f, "^{}_{}", debruijn.index(), bound_ty.var.index())
1198 ty::BoundTyKind::Param(p) => write!(f, "{}", p),
1201 Adt(def, substs) => cx.parameterized(f, def.did, substs, iter::empty()),
1202 Dynamic(data, r) => {
1203 let print_r = r.display_outputs_anything(cx);
1210 print!(f, cx, write(" + "), print_display(r), write(")"))?;
1214 Foreign(def_id) => {
1215 cx.parameterized(f, def_id, subst::InternalSubsts::empty(), iter::empty())
1217 Projection(ref data) => data.print(f, cx),
1218 UnnormalizedProjection(ref data) => {
1219 write!(f, "Unnormalized(")?;
1223 Placeholder(placeholder) => {
1224 write!(f, "Placeholder({:?})", placeholder)
1226 Opaque(def_id, substs) => {
1228 return write!(f, "Opaque({:?}, {:?})", def_id, substs);
1231 let def_key = cx.tcx.def_key(def_id);
1232 if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
1233 write!(f, "{}", name)?;
1234 let mut substs = substs.iter();
1235 if let Some(first) = substs.next() {
1237 write!(f, "{}", first)?;
1238 for subst in substs {
1239 write!(f, ", {}", subst)?;
1245 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1246 // by looking up the projections associated with the def_id.
1247 let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs);
1249 let mut first = true;
1250 let mut is_sized = false;
1252 for predicate in bounds.predicates {
1253 if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
1254 // Don't print +Sized, but rather +?Sized if absent.
1255 if Some(trait_ref.def_id()) == cx.tcx.lang_items().sized_trait() {
1261 write("{}", if first { " " } else { "+" }),
1267 write!(f, "{}?Sized", if first { " " } else { "+" })?;
1269 write!(f, " Sized")?;
1273 Str => write!(f, "str"),
1274 Generator(did, substs, movability) => {
1275 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1276 let witness = substs.witness(did, cx.tcx);
1277 if movability == hir::GeneratorMovability::Movable {
1278 write!(f, "[generator")?;
1280 write!(f, "[static generator")?;
1283 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1284 write!(f, "@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))?;
1286 cx.tcx.with_freevars(hir_id, |freevars| {
1287 for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1291 cx.tcx.hir().name(freevar.var_id())),
1298 // cross-crate closure types should only be
1299 // visible in codegen bug reports, I imagine.
1300 write!(f, "@{:?}", did)?;
1302 for (index, upvar_ty) in upvar_tys.enumerate() {
1304 write("{}{}:", sep, index),
1310 print!(f, cx, write(" "), print(witness), write("]"))
1312 GeneratorWitness(types) => {
1313 cx.in_binder(f, &types)
1315 Closure(did, substs) => {
1316 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1317 write!(f, "[closure")?;
1319 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1320 if cx.tcx.sess.opts.debugging_opts.span_free_formats {
1321 write!(f, "@{:?}", hir_id)?;
1323 write!(f, "@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))?;
1326 cx.tcx.with_freevars(hir_id, |freevars| {
1327 for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1331 cx.tcx.hir().name(freevar.var_id())),
1338 // cross-crate closure types should only be
1339 // visible in codegen bug reports, I imagine.
1340 write!(f, "@{:?}", did)?;
1342 for (index, upvar_ty) in upvar_tys.enumerate() {
1344 write("{}{}:", sep, index),
1353 " closure_kind_ty={:?} closure_sig_ty={:?}",
1354 substs.closure_kind_ty(did, cx.tcx),
1355 substs.closure_sig_ty(did, cx.tcx),
1362 print!(f, cx, write("["), print(ty), write("; "))?;
1364 ty::LazyConst::Unevaluated(_def_id, _substs) => {
1367 ty::LazyConst::Evaluated(c) => {
1369 ConstValue::Infer(..) => write!(f, "_")?,
1370 ConstValue::Param(ParamConst { name, .. }) =>
1371 write!(f, "{}", name)?,
1372 _ => write!(f, "{}", c.unwrap_usize(cx.tcx))?,
1379 print!(f, cx, write("["), print(ty), write("]"))
1384 self.print_display(f, cx)
1390 ('tcx) ConstValue<'tcx>, (self, f, cx) {
1393 ConstValue::Infer(..) => write!(f, "_"),
1394 ConstValue::Param(ParamConst { name, .. }) => write!(f, "{}", name),
1395 _ => write!(f, "{:?}", self),
1402 ('tcx) ty::Const<'tcx>, (self, f, cx) {
1404 write!(f, "{} : {}", self.val, self.ty)
1410 ('tcx) ty::LazyConst<'tcx>, (self, f, cx) {
1413 ty::LazyConst::Unevaluated(..) => write!(f, "_ : _"),
1414 ty::LazyConst::Evaluated(c) => write!(f, "{}", c),
1421 () ty::ParamTy, (self, f, cx) {
1423 write!(f, "{}", self.name)
1426 write!(f, "{}/#{}", self.name, self.idx)
1432 () ty::ParamConst, (self, f, cx) {
1434 write!(f, "{}", self.name)
1437 write!(f, "{}/#{}", self.name, self.index)
1442 // Similar problem to `Binder<T>`, can't define a generic impl.
1443 define_print_multi! {
1445 ('tcx) ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
1446 ('tcx) ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
1450 print!(f, cx, print(self.0), write(" : "), print(self.1))
1456 ('tcx) ty::SubtypePredicate<'tcx>, (self, f, cx) {
1458 print!(f, cx, print(self.a), write(" <: "), print(self.b))
1464 ('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) {
1466 write!(f, "TraitPredicate({:?})",
1470 print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1476 ('tcx) ty::ProjectionPredicate<'tcx>, (self, f, cx) {
1479 write("ProjectionPredicate("),
1480 print(self.projection_ty),
1486 print!(f, cx, print(self.projection_ty), write(" == "), print(self.ty))
1492 ('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) {
1494 cx.parameterized(f, self.item_def_id, self.substs, iter::empty())
1500 () ty::ClosureKind, (self, f, cx) {
1503 ty::ClosureKind::Fn => write!(f, "Fn"),
1504 ty::ClosureKind::FnMut => write!(f, "FnMut"),
1505 ty::ClosureKind::FnOnce => write!(f, "FnOnce"),
1512 ('tcx) ty::Predicate<'tcx>, (self, f, cx) {
1515 ty::Predicate::Trait(ref data) => data.print(f, cx),
1516 ty::Predicate::Subtype(ref predicate) => predicate.print(f, cx),
1517 ty::Predicate::RegionOutlives(ref predicate) => predicate.print(f, cx),
1518 ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx),
1519 ty::Predicate::Projection(ref predicate) => predicate.print(f, cx),
1520 ty::Predicate::WellFormed(ty) => print!(f, cx, print(ty), write(" well-formed")),
1521 ty::Predicate::ObjectSafe(trait_def_id) => {
1522 write!(f, "the trait `{}` is object-safe", cx.tcx.item_path_str(trait_def_id))
1524 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
1525 write!(f, "the closure `{}` implements the trait `{}`",
1526 cx.tcx.item_path_str(closure_def_id), kind)
1528 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1529 write!(f, "the constant `")?;
1530 cx.parameterized(f, def_id, substs, iter::empty())?;
1531 write!(f, "` can be evaluated")
1537 ty::Predicate::Trait(ref a) => a.print(f, cx),
1538 ty::Predicate::Subtype(ref pair) => pair.print(f, cx),
1539 ty::Predicate::RegionOutlives(ref pair) => pair.print(f, cx),
1540 ty::Predicate::TypeOutlives(ref pair) => pair.print(f, cx),
1541 ty::Predicate::Projection(ref pair) => pair.print(f, cx),
1542 ty::Predicate::WellFormed(ty) => ty.print(f, cx),
1543 ty::Predicate::ObjectSafe(trait_def_id) => {
1544 write!(f, "ObjectSafe({:?})", trait_def_id)
1546 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
1547 write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
1549 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1550 write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
1558 ('tcx) Kind<'tcx>, (self, f, cx) {
1560 match self.unpack() {
1561 UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)),
1562 UnpackedKind::Type(ty) => print!(f, cx, print(ty)),
1563 UnpackedKind::Const(ct) => print!(f, cx, print(ct)),
1567 match self.unpack() {
1568 UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)),
1569 UnpackedKind::Type(ty) => print!(f, cx, print(ty)),
1570 UnpackedKind::Const(ct) => print!(f, cx, print(ct)),