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::{FmtPrinter, 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(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)+, F: fmt::Write> Print<'tcx, FmtPrinter<F>> for $target {
196 type Output = fmt::Result;
197 fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter<F>>) -> fmt::Result {
203 ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
204 impl<F: fmt::Write> Print<'tcx, FmtPrinter<F>> for $target {
205 type Output = fmt::Result;
206 fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter<F>>) -> fmt::Result {
212 ( $generic:tt $target:ty,
213 $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
214 gen_print_impl! { $generic $target, $vars $disp $dbg }
215 gen_display_debug! { $generic $target, display $gendisp }
216 gen_display_debug! { $generic $target, debug $gendbg }
219 macro_rules! define_print {
220 ( $generic:tt $target:ty,
221 $vars:tt { display $disp:block debug $dbg:block } ) => {
222 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
224 ( $generic:tt $target:ty,
225 $vars:tt { debug $dbg:block display $disp:block } ) => {
226 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
228 ( $generic:tt $target:ty,
229 $vars:tt { debug $dbg:block } ) => {
230 gen_print_impl! { $generic $target, $vars no {
231 bug!(concat!("display not implemented for ", stringify!($target)));
234 ( $generic:tt $target:ty,
235 ($self:ident, $cx:ident) { display $disp:block } ) => {
236 gen_print_impl! { $generic $target, ($self, $cx) yes $disp no {
237 write!($cx.printer.fmt, "{:?}", $self)
241 macro_rules! define_print_multi {
242 ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
243 $(define_print! { $generic $target, $vars $def })*
246 macro_rules! print_inner {
247 ( $cx:expr, write ($($data:expr),+) ) => {
248 write!($cx.printer.fmt, $($data),+)
250 ( $cx:expr, $kind:ident ($data:expr) ) => {
255 ( $cx:expr $(, $kind:ident $data:tt)+ ) => {
256 Ok(())$(.and_then(|_| print_inner!($cx, $kind $data)))+
260 impl<F: fmt::Write> PrintCx<'a, 'gcx, 'tcx, FmtPrinter<F>> {
267 print!(self, write("("))?;
268 let mut inputs = inputs.iter();
269 if let Some(&ty) = inputs.next() {
270 print!(self, print_display(ty))?;
272 print!(self, write(", "), print_display(ty))?;
275 print!(self, write(", ..."))?;
278 print!(self, write(")"))?;
279 if !output.is_unit() {
280 print!(self, write(" -> "), print_display(output))?;
289 substs: SubstsRef<'tcx>,
290 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
292 let mut key = self.tcx.def_key(def_id);
293 let is_value_ns = match key.disambiguated_data.data {
294 DefPathData::ValueNs(_) |
295 DefPathData::EnumVariant(_) => true,
297 // Skip `StructCtor` so that `Struct::<T>` will be printed,
298 // instead of the less pretty `Struct<T>::{{constructor}}`.
299 DefPathData::StructCtor => {
300 def_id.index = key.parent.unwrap();
301 key = self.tcx.def_key(def_id);
308 let generics = self.tcx.generics_of(def_id);
310 if let Some(parent_def_id) = generics.parent {
311 assert_eq!(parent_def_id, DefId { index: key.parent.unwrap(), ..def_id });
313 let parent_generics = self.tcx.generics_of(parent_def_id);
314 let parent_has_own_self =
315 parent_generics.has_self && parent_generics.parent_count == 0;
316 if parent_has_own_self {
317 print!(self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
319 self.parameterized(parent_def_id, substs, iter::empty())?;
320 if parent_has_own_self {
321 print!(self, write(">"))?;
324 print!(self, write("::{}", key.disambiguated_data.data.as_interned_str()))?;
326 // Try to print `impl`s more like how you'd refer to their associated items.
327 if let DefPathData::Impl = key.disambiguated_data.data {
328 if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
329 // HACK(eddyb) this is in lieu of more specific disambiguation.
330 print!(self, write("{}", self.tcx.item_path_str(def_id)))?;
332 let trait_ref = trait_ref.subst(self.tcx, substs);
333 print!(self, print_debug(trait_ref))?;
335 let self_ty = self.tcx.type_of(def_id).subst(self.tcx, substs);
336 // FIXME(eddyb) omit the <> where possible.
337 print!(self, write("<"), print(self_ty), write(">"))?;
342 print!(self, write("{}", self.tcx.item_path_str(def_id)))?;
345 let mut empty = true;
346 let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
349 print!(cx, write("{}", start))
351 print!(cx, write("{}", cont))
355 let start = if is_value_ns { "::<" } else { "<" };
357 let has_own_self = generics.has_self && generics.parent_count == 0;
358 let params = &generics.params[has_own_self as usize..];
360 // Don't print any regions if they're all erased.
361 let print_regions = params.iter().any(|param| {
362 match substs[param.index as usize].unpack() {
363 UnpackedKind::Lifetime(r) => *r != ty::ReErased,
368 // Don't print args that are the defaults of their respective parameters.
369 let num_supplied_defaults = if self.is_verbose {
372 params.iter().rev().take_while(|param| {
374 ty::GenericParamDefKind::Lifetime => false,
375 ty::GenericParamDefKind::Type { has_default, .. } => {
376 has_default && substs[param.index as usize] == Kind::from(
377 self.tcx.type_of(param.def_id).subst(self.tcx, substs)
380 ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
385 for param in ¶ms[..params.len() - num_supplied_defaults] {
386 match substs[param.index as usize].unpack() {
387 UnpackedKind::Lifetime(region) => {
391 start_or_continue(self, start, ", ")?;
392 if !region.display_outputs_anything(self) {
393 // This happens when the value of the region
394 // parameter is not easily serialized. This may be
395 // because the user omitted it in the first place,
396 // or because it refers to some block in the code,
397 // etc. I'm not sure how best to serialize this.
398 print!(self, write("'_"))?;
400 region.print_display(self)?;
403 UnpackedKind::Type(ty) => {
404 start_or_continue(self, start, ", ")?;
405 ty.print_display(self)?;
407 UnpackedKind::Const(ct) => {
408 start_or_continue(self, start, ", ")?;
409 ct.print_display(self)?;
414 for projection in projections {
415 start_or_continue(self, start, ", ")?;
418 self.tcx.associated_item(projection.item_def_id).ident),
419 print_display(projection.ty))?;
422 start_or_continue(self, "", ">")
425 fn in_binder<T>(&mut self, value: &ty::Binder<T>) -> fmt::Result
426 where T: Print<'tcx, FmtPrinter<F>, Output = fmt::Result> + TypeFoldable<'tcx>
428 fn name_by_region_index(index: usize) -> InternedString {
430 0 => Symbol::intern("'r"),
431 1 => Symbol::intern("'s"),
432 i => Symbol::intern(&format!("'t{}", i-2)),
436 // Replace any anonymous late-bound regions with named
437 // variants, using gensym'd identifiers, so that we can
438 // clearly differentiate between named and unnamed regions in
439 // the output. We'll probably want to tweak this over time to
440 // decide just how much information to give.
441 if self.binder_depth == 0 {
442 self.prepare_late_bound_region_info(value);
445 let mut empty = true;
446 let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
449 print!(cx, write("{}", start))
451 print!(cx, write("{}", cont))
455 let old_region_index = self.region_index;
456 let mut region_index = old_region_index;
457 let new_value = self.tcx.replace_late_bound_regions(value, |br| {
458 let _ = start_or_continue(self, "for<", ", ");
460 ty::BrNamed(_, name) => {
461 let _ = print!(self, write("{}", name));
468 let name = name_by_region_index(region_index);
470 if !self.is_name_used(&name) {
474 let _ = print!(self, write("{}", name));
475 ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name)
478 self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
480 start_or_continue(self, "", "> ")?;
482 // Push current state to gcx, and restore after writing new_value.
483 self.binder_depth += 1;
484 self.region_index = region_index;
485 let result = new_value.print_display(self);
486 self.region_index = old_region_index;
487 self.binder_depth -= 1;
491 fn is_name_used(&self, name: &InternedString) -> bool {
492 match self.used_region_names {
493 Some(ref names) => names.contains(name),
499 pub fn parameterized<F: fmt::Write>(f: &mut F, did: DefId, substs: SubstsRef<'_>) -> fmt::Result {
500 PrintCx::with(FmtPrinter { fmt: f }, |mut cx| {
501 let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
502 cx.parameterized(did, substs, iter::empty())
506 impl<'a, 'tcx, P, T: Print<'tcx, P>> Print<'tcx, P> for &'a T {
507 type Output = T::Output;
508 fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output {
514 ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, cx) {
516 // Generate the main trait ref, including associated types.
517 let mut first = true;
519 if let Some(principal) = self.principal() {
520 let mut resugared_principal = false;
522 // Special-case `Fn(...) -> ...` and resugar it.
523 if !cx.is_verbose && cx.tcx.lang_items().fn_trait_kind(principal.def_id).is_some() {
524 if let Tuple(ref args) = principal.substs.type_at(0).sty {
525 let mut projections = self.projection_bounds();
526 if let (Some(proj), None) = (projections.next(), projections.next()) {
527 print!(cx, write("{}", cx.tcx.item_path_str(principal.def_id)))?;
528 cx.fn_sig(args, false, proj.ty)?;
529 resugared_principal = true;
534 if !resugared_principal {
535 // Use a type that can't appear in defaults of type parameters.
536 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
537 let principal = principal.with_self_ty(cx.tcx, dummy_self);
541 self.projection_bounds(),
548 let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
549 cx.tcx.item_path_str(did)
552 // The auto traits come ordered by `DefPathHash`. While
553 // `DefPathHash` is *stable* in the sense that it depends on
554 // neither the host nor the phase of the moon, it depends
555 // "pseudorandomly" on the compiler version and the target.
557 // To avoid that causing instabilities in compiletest
558 // output, sort the auto-traits alphabetically.
561 for auto_trait in auto_traits {
563 print!(cx, write(" + "))?;
567 print!(cx, write("{}", auto_trait))?;
575 impl fmt::Debug for ty::GenericParamDef {
576 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
577 let type_name = match self.kind {
578 ty::GenericParamDefKind::Lifetime => "Lifetime",
579 ty::GenericParamDefKind::Type { .. } => "Type",
580 ty::GenericParamDefKind::Const => "Const",
582 write!(f, "{}({}, {:?}, {})",
590 impl fmt::Debug for ty::TraitDef {
591 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
592 PrintCx::with(FmtPrinter { fmt: f }, |cx| {
593 print!(cx, write("{}", cx.tcx.item_path_str(self.def_id)))
598 impl fmt::Debug for ty::AdtDef {
599 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600 PrintCx::with(FmtPrinter { fmt: f }, |cx| {
601 print!(cx, write("{}", cx.tcx.item_path_str(self.did)))
606 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
607 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
608 write!(f, "ClosureUpvar({:?},{:?})",
614 impl fmt::Debug for ty::UpvarId {
615 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
616 PrintCx::with(FmtPrinter { fmt: f }, |cx| {
617 print!(cx, write("UpvarId({:?};`{}`;{:?})",
618 self.var_path.hir_id,
619 cx.tcx.hir().name_by_hir_id(self.var_path.hir_id),
620 self.closure_expr_id))
625 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
626 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627 write!(f, "UpvarBorrow({:?}, {:?})",
628 self.kind, self.region)
633 ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, cx) {
635 print!(cx, write("{{"))?;
636 let mut tys = self.iter();
637 if let Some(&ty) = tys.next() {
638 print!(cx, print(ty))?;
640 print!(cx, write(", "), print(ty))?;
643 print!(cx, write("}}"))
649 ('tcx) ty::TypeAndMut<'tcx>, (self, cx) {
652 write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
659 ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) {
661 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
663 let trait_ref = *ty::Binder::bind(*self)
664 .with_self_ty(cx.tcx, dummy_self)
666 cx.parameterized(trait_ref.def_id, trait_ref.substs, iter::empty())
669 self.print_display(cx)
675 ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) {
677 print!(cx, write("{:?} -> ", self.kind), print(self.target))
683 () ty::BoundRegion, (self, cx) {
686 return self.print_debug(cx);
689 if let BrNamed(_, name) = *self {
690 if name != "" && name != "'_" {
691 return print!(cx, write("{}", name));
695 let highlight = RegionHighlightMode::get();
696 if let Some((region, counter)) = highlight.highlight_bound_region {
698 return print!(cx, write("'{}", counter));
706 BrAnon(n) => print!(cx, write("BrAnon({:?})", n)),
707 BrFresh(n) => print!(cx, write("BrFresh({:?})", n)),
708 BrNamed(did, name) => {
709 print!(cx, write("BrNamed({:?}:{:?}, {})",
710 did.krate, did.index, name))
712 BrEnv => print!(cx, write("BrEnv")),
718 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
720 // NB: this must be kept in sync with the printing logic above.
721 impl ty::BoundRegion {
722 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
727 if let BrNamed(_, name) = *self {
728 if name != "" && name != "'_" {
733 let highlight = RegionHighlightMode::get();
734 if let Some((region, _)) = highlight.highlight_bound_region {
745 () ty::PlaceholderRegion, (self, cx) {
748 return self.print_debug(cx);
751 let highlight = RegionHighlightMode::get();
752 if let Some(counter) = highlight.placeholder_highlight(*self) {
753 return print!(cx, write("'{}", counter));
756 print!(cx, print_display(self.name))
761 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
763 // NB: this must be kept in sync with the printing logic above.
764 impl ty::PlaceholderRegion {
765 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
770 let highlight = RegionHighlightMode::get();
771 if highlight.placeholder_highlight(*self).is_some() {
775 self.name.display_outputs_anything(cx)
780 () ty::RegionKind, (self, cx) {
783 return self.print_debug(cx);
786 // Watch out for region highlights.
787 if let Some(n) = RegionHighlightMode::get().region_highlighted(self) {
788 return print!(cx, write("'{:?}", n));
791 // These printouts are concise. They do not contain all the information
792 // the user might want to diagnose an error, but there is basically no way
793 // to fit that into a short string. Hence the recommendation to use
794 // `explain_region()` or `note_and_explain_region()`.
796 ty::ReEarlyBound(ref data) => {
797 if data.name != "'_" {
798 print!(cx, write("{}", data.name))
803 ty::ReLateBound(_, br) |
804 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
805 print!(cx, print_display(br))
807 ty::RePlaceholder(p) => {
808 print!(cx, print_display(p))
810 ty::ReScope(scope) if cx.identify_regions => {
812 region::ScopeData::Node =>
813 print!(cx, write("'{}s", scope.item_local_id().as_usize())),
814 region::ScopeData::CallSite =>
815 print!(cx, write("'{}cs", scope.item_local_id().as_usize())),
816 region::ScopeData::Arguments =>
817 print!(cx, write("'{}as", scope.item_local_id().as_usize())),
818 region::ScopeData::Destruction =>
819 print!(cx, write("'{}ds", scope.item_local_id().as_usize())),
820 region::ScopeData::Remainder(first_statement_index) => print!(cx, write(
822 scope.item_local_id().as_usize(),
823 first_statement_index.index()
827 ty::ReVar(region_vid) if cx.identify_regions => {
828 print!(cx, print_debug(region_vid))
830 ty::ReVar(region_vid) => {
831 print!(cx, print_display(region_vid))
834 ty::ReErased => Ok(()),
835 ty::ReStatic => print!(cx, write("'static")),
836 ty::ReEmpty => print!(cx, write("'<empty>")),
838 // The user should never encounter these in unsubstituted form.
839 ty::ReClosureBound(vid) => print!(cx, write("{:?}", vid)),
844 ty::ReEarlyBound(ref data) => {
845 print!(cx, write("ReEarlyBound({}, {})",
850 ty::ReClosureBound(ref vid) => {
851 print!(cx, write("ReClosureBound({:?})",
855 ty::ReLateBound(binder_id, ref bound_region) => {
856 print!(cx, write("ReLateBound({:?}, {:?})",
861 ty::ReFree(ref fr) => print!(cx, write("{:?}", fr)),
864 print!(cx, write("ReScope({:?})", id))
867 ty::ReStatic => print!(cx, write("ReStatic")),
869 ty::ReVar(ref vid) => {
870 print!(cx, write("{:?}", vid))
873 ty::RePlaceholder(placeholder) => {
874 print!(cx, write("RePlaceholder({:?})", placeholder))
877 ty::ReEmpty => print!(cx, write("ReEmpty")),
879 ty::ReErased => print!(cx, write("ReErased"))
885 // HACK(eddyb) Trying to print a lifetime might not print anything, which
886 // may need special handling in the caller (of `ty::RegionKind::print`).
887 // To avoid printing to a temporary string, the `display_outputs_anything`
888 // method can instead be used to determine this, ahead of time.
890 // NB: this must be kept in sync with the printing logic above.
891 impl ty::RegionKind {
892 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
897 if RegionHighlightMode::get().region_highlighted(self).is_some() {
902 ty::ReEarlyBound(ref data) => {
903 data.name != "" && data.name != "'_"
906 ty::ReLateBound(_, br) |
907 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
908 br.display_outputs_anything(cx)
911 ty::RePlaceholder(p) => p.display_outputs_anything(cx),
914 ty::ReVar(_) if cx.identify_regions => true,
916 ty::ReVar(region_vid) => region_vid.display_outputs_anything(cx),
919 ty::ReErased => false,
923 ty::ReClosureBound(_) => true,
929 () ty::FreeRegion, (self, cx) {
931 print!(cx, write("ReFree({:?}, {:?})", self.scope, self.bound_region))
937 () ty::Variance, (self, cx) {
939 cx.printer.fmt.write_str(match *self {
940 ty::Covariant => "+",
941 ty::Contravariant => "-",
942 ty::Invariant => "o",
943 ty::Bivariant => "*",
950 ('tcx) ty::FnSig<'tcx>, (self, cx) {
952 if self.unsafety == hir::Unsafety::Unsafe {
953 print!(cx, write("unsafe "))?;
956 if self.abi != Abi::Rust {
957 print!(cx, write("extern {} ", self.abi))?;
960 print!(cx, write("fn"))?;
961 cx.fn_sig(self.inputs(), self.c_variadic, self.output())
964 print!(cx, write("({:?}; c_variadic: {})->{:?}",
965 self.inputs(), self.c_variadic, self.output()))
970 impl fmt::Debug for ty::TyVid {
971 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
972 write!(f, "_#{}t", self.index)
976 impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
977 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
978 write!(f, "_#{}f", self.index)
982 impl fmt::Debug for ty::IntVid {
983 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
984 write!(f, "_#{}i", self.index)
988 impl fmt::Debug for ty::FloatVid {
989 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
990 write!(f, "_#{}f", self.index)
995 () ty::RegionVid, (self, cx) {
998 return self.print_debug(cx);
1001 let highlight = RegionHighlightMode::get();
1002 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
1003 return print!(cx, write("'{:?}", counter));
1009 // HACK(eddyb) this is duplicated from `display` printing,
1010 // to keep NLL borrowck working even with `-Zverbose`.
1011 let highlight = RegionHighlightMode::get();
1012 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
1013 return print!(cx, write("'{:?}", counter));
1016 print!(cx, write("'_#{}r", self.index()))
1021 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
1023 // NB: this must be kept in sync with the printing logic above.
1024 impl ty::RegionVid {
1025 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
1030 let highlight = RegionHighlightMode::get();
1031 if highlight.region_highlighted(&ty::ReVar(*self)).is_some() {
1040 () ty::InferTy, (self, cx) {
1043 return self.print_debug(cx);
1046 ty::TyVar(_) => print!(cx, write("_")),
1047 ty::IntVar(_) => print!(cx, write("{}", "{integer}")),
1048 ty::FloatVar(_) => print!(cx, write("{}", "{float}")),
1049 ty::FreshTy(v) => print!(cx, write("FreshTy({})", v)),
1050 ty::FreshIntTy(v) => print!(cx, write("FreshIntTy({})", v)),
1051 ty::FreshFloatTy(v) => print!(cx, write("FreshFloatTy({})", v))
1056 ty::TyVar(ref v) => print!(cx, write("{:?}", v)),
1057 ty::IntVar(ref v) => print!(cx, write("{:?}", v)),
1058 ty::FloatVar(ref v) => print!(cx, write("{:?}", v)),
1059 ty::FreshTy(v) => print!(cx, write("FreshTy({:?})", v)),
1060 ty::FreshIntTy(v) => print!(cx, write("FreshIntTy({:?})", v)),
1061 ty::FreshFloatTy(v) => print!(cx, write("FreshFloatTy({:?})", v))
1067 impl fmt::Debug for ty::IntVarValue {
1068 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1070 ty::IntType(ref v) => v.fmt(f),
1071 ty::UintType(ref v) => v.fmt(f),
1076 impl fmt::Debug for ty::FloatVarValue {
1077 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1082 // The generic impl doesn't work yet because projections are not
1083 // normalized under HRTB.
1084 /*impl<T> fmt::Display for ty::Binder<T>
1085 where T: fmt::Display + for<'a> ty::Lift<'a>,
1086 for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
1088 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1089 PrintCx::with(|cx| cx.in_binder(cx.tcx.lift(self)
1090 .expect("could not lift for printing")))
1094 define_print_multi! {
1096 ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
1097 ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
1098 ('tcx) ty::Binder<ty::FnSig<'tcx>>,
1099 ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
1100 ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
1101 ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
1102 ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
1103 ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
1113 ('tcx) ty::TraitRef<'tcx>, (self, cx) {
1115 cx.parameterized(self.def_id, self.substs, iter::empty())
1118 print!(cx, write("<"), print(self.self_ty()), write(" as "))?;
1119 cx.parameterized(self.def_id, self.substs, iter::empty())?;
1120 print!(cx, write(">"))
1126 ('tcx) ty::Ty<'tcx>, (self, cx) {
1129 Bool => print!(cx, write("bool")),
1130 Char => print!(cx, write("char")),
1131 Int(t) => print!(cx, write("{}", t.ty_to_string())),
1132 Uint(t) => print!(cx, write("{}", t.ty_to_string())),
1133 Float(t) => print!(cx, write("{}", t.ty_to_string())),
1135 print!(cx, write("*{} ", match tm.mutbl {
1136 hir::MutMutable => "mut",
1137 hir::MutImmutable => "const",
1141 Ref(r, ty, mutbl) => {
1142 print!(cx, write("&"))?;
1143 if r.display_outputs_anything(cx) {
1144 print!(cx, print_display(r), write(" "))?;
1146 ty::TypeAndMut { ty, mutbl }.print(cx)
1148 Never => print!(cx, write("!")),
1150 print!(cx, write("("))?;
1151 let mut tys = tys.iter();
1152 if let Some(&ty) = tys.next() {
1153 print!(cx, print(ty), write(","))?;
1154 if let Some(&ty) = tys.next() {
1155 print!(cx, write(" "), print(ty))?;
1157 print!(cx, write(", "), print(ty))?;
1161 print!(cx, write(")"))
1163 FnDef(def_id, substs) => {
1164 let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs);
1165 print!(cx, print(sig), write(" {{"))?;
1166 cx.parameterized(def_id, substs, iter::empty())?;
1167 print!(cx, write("}}"))
1169 FnPtr(ref bare_fn) => {
1172 Infer(infer_ty) => print!(cx, write("{}", infer_ty)),
1173 Error => print!(cx, write("[type error]")),
1174 Param(ref param_ty) => print!(cx, write("{}", param_ty)),
1175 Bound(debruijn, bound_ty) => {
1176 match bound_ty.kind {
1177 ty::BoundTyKind::Anon => {
1178 if debruijn == ty::INNERMOST {
1179 print!(cx, write("^{}", bound_ty.var.index()))
1181 print!(cx, write("^{}_{}", debruijn.index(), bound_ty.var.index()))
1185 ty::BoundTyKind::Param(p) => print!(cx, write("{}", p)),
1188 Adt(def, substs) => cx.parameterized(def.did, substs, iter::empty()),
1189 Dynamic(data, r) => {
1190 let print_r = r.display_outputs_anything(cx);
1192 print!(cx, write("("))?;
1194 print!(cx, write("dyn "))?;
1197 print!(cx, write(" + "), print_display(r), write(")"))?;
1201 Foreign(def_id) => {
1202 cx.parameterized(def_id, subst::InternalSubsts::empty(), iter::empty())
1204 Projection(ref data) => data.print(cx),
1205 UnnormalizedProjection(ref data) => {
1206 print!(cx, write("Unnormalized("))?;
1208 print!(cx, write(")"))
1210 Placeholder(placeholder) => {
1211 print!(cx, write("Placeholder({:?})", placeholder))
1213 Opaque(def_id, substs) => {
1215 return print!(cx, write("Opaque({:?}, {:?})", def_id, substs));
1218 let def_key = cx.tcx.def_key(def_id);
1219 if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
1220 print!(cx, write("{}", name))?;
1221 let mut substs = substs.iter();
1222 // FIXME(eddyb) print this with `parameterized`.
1223 if let Some(first) = substs.next() {
1224 print!(cx, write("::<"))?;
1225 print!(cx, write("{}", first))?;
1226 for subst in substs {
1227 print!(cx, write(", {}", subst))?;
1229 print!(cx, write(">"))?;
1233 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1234 // by looking up the projections associated with the def_id.
1235 let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs);
1237 let mut first = true;
1238 let mut is_sized = false;
1239 print!(cx, write("impl"))?;
1240 for predicate in bounds.predicates {
1241 if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
1242 // Don't print +Sized, but rather +?Sized if absent.
1243 if Some(trait_ref.def_id()) == cx.tcx.lang_items().sized_trait() {
1249 write("{}", if first { " " } else { "+" }),
1255 print!(cx, write("{}?Sized", if first { " " } else { "+" }))?;
1257 print!(cx, write(" Sized"))?;
1261 Str => print!(cx, write("str")),
1262 Generator(did, substs, movability) => {
1263 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1264 let witness = substs.witness(did, cx.tcx);
1265 if movability == hir::GeneratorMovability::Movable {
1266 print!(cx, write("[generator"))?;
1268 print!(cx, write("[static generator"))?;
1271 // FIXME(eddyb) should use `def_span`.
1272 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1273 print!(cx, write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?;
1275 cx.tcx.with_freevars(hir_id, |freevars| {
1276 for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1280 cx.tcx.hir().name(freevar.var_id())),
1287 // cross-crate closure types should only be
1288 // visible in codegen bug reports, I imagine.
1289 print!(cx, write("@{:?}", did))?;
1291 for (index, upvar_ty) in upvar_tys.enumerate() {
1293 write("{}{}:", sep, index),
1299 print!(cx, write(" "), print(witness), write("]"))
1301 GeneratorWitness(types) => {
1302 cx.in_binder(&types)
1304 Closure(did, substs) => {
1305 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1306 print!(cx, write("[closure"))?;
1308 // FIXME(eddyb) should use `def_span`.
1309 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1310 if cx.tcx.sess.opts.debugging_opts.span_free_formats {
1311 print!(cx, write("@{:?}", hir_id))?;
1313 print!(cx, write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?;
1316 cx.tcx.with_freevars(hir_id, |freevars| {
1317 for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1321 cx.tcx.hir().name(freevar.var_id())),
1328 // cross-crate closure types should only be
1329 // visible in codegen bug reports, I imagine.
1330 print!(cx, write("@{:?}", did))?;
1332 for (index, upvar_ty) in upvar_tys.enumerate() {
1334 write("{}{}:", sep, index),
1342 " closure_kind_ty={:?} closure_sig_ty={:?}",
1343 substs.closure_kind_ty(did, cx.tcx),
1344 substs.closure_sig_ty(did, cx.tcx)
1348 print!(cx, write("]"))
1351 print!(cx, write("["), print(ty), write("; "))?;
1353 ty::LazyConst::Unevaluated(_def_id, _substs) => {
1354 print!(cx, write("_"))?;
1356 ty::LazyConst::Evaluated(c) => {
1358 ConstValue::Infer(..) => print!(cx, write("_"))?,
1359 ConstValue::Param(ParamConst { name, .. }) =>
1360 print!(cx, write("{}", name))?,
1361 _ => print!(cx, write("{}", c.unwrap_usize(cx.tcx)))?,
1365 print!(cx, write("]"))
1368 print!(cx, write("["), print(ty), write("]"))
1373 self.print_display(cx)
1379 ('tcx) ConstValue<'tcx>, (self, cx) {
1382 ConstValue::Infer(..) => print!(cx, write("_")),
1383 ConstValue::Param(ParamConst { name, .. }) => print!(cx, write("{}", name)),
1384 _ => print!(cx, write("{:?}", self)),
1391 ('tcx) ty::Const<'tcx>, (self, cx) {
1393 print!(cx, write("{} : {}", self.val, self.ty))
1399 ('tcx) ty::LazyConst<'tcx>, (self, cx) {
1402 // FIXME(const_generics) this should print at least the type.
1403 ty::LazyConst::Unevaluated(..) => print!(cx, write("_ : _")),
1404 ty::LazyConst::Evaluated(c) => print!(cx, write("{}", c)),
1411 () ty::ParamTy, (self, cx) {
1413 print!(cx, write("{}", self.name))
1416 print!(cx, write("{}/#{}", self.name, self.idx))
1422 () ty::ParamConst, (self, cx) {
1424 print!(cx, write("{}", self.name))
1427 print!(cx, write("{}/#{}", self.name, self.index))
1432 // Similar problem to `Binder<T>`, can't define a generic impl.
1433 define_print_multi! {
1435 ('tcx) ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
1436 ('tcx) ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
1440 print!(cx, print(self.0), write(" : "), print(self.1))
1446 ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) {
1448 print!(cx, print(self.a), write(" <: "), print(self.b))
1454 ('tcx) ty::TraitPredicate<'tcx>, (self, cx) {
1456 print!(cx, write("TraitPredicate({:?})",
1460 print!(cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1466 ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) {
1469 write("ProjectionPredicate("),
1470 print(self.projection_ty),
1476 print!(cx, print(self.projection_ty), write(" == "), print(self.ty))
1482 ('tcx) ty::ProjectionTy<'tcx>, (self, cx) {
1484 cx.parameterized(self.item_def_id, self.substs, iter::empty())
1490 () ty::ClosureKind, (self, cx) {
1493 ty::ClosureKind::Fn => print!(cx, write("Fn")),
1494 ty::ClosureKind::FnMut => print!(cx, write("FnMut")),
1495 ty::ClosureKind::FnOnce => print!(cx, write("FnOnce")),
1502 ('tcx) ty::Predicate<'tcx>, (self, cx) {
1505 ty::Predicate::Trait(ref data) => data.print(cx),
1506 ty::Predicate::Subtype(ref predicate) => predicate.print(cx),
1507 ty::Predicate::RegionOutlives(ref predicate) => predicate.print(cx),
1508 ty::Predicate::TypeOutlives(ref predicate) => predicate.print(cx),
1509 ty::Predicate::Projection(ref predicate) => predicate.print(cx),
1510 ty::Predicate::WellFormed(ty) => print!(cx, print(ty), write(" well-formed")),
1511 ty::Predicate::ObjectSafe(trait_def_id) => {
1512 print!(cx, write("the trait `{}` is object-safe",
1513 cx.tcx.item_path_str(trait_def_id)))
1515 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
1516 print!(cx, write("the closure `{}` implements the trait `{}`",
1517 cx.tcx.item_path_str(closure_def_id), kind))
1519 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1520 print!(cx, write("the constant `"))?;
1521 cx.parameterized(def_id, substs, iter::empty())?;
1522 print!(cx, write("` can be evaluated"))
1528 ty::Predicate::Trait(ref a) => a.print(cx),
1529 ty::Predicate::Subtype(ref pair) => pair.print(cx),
1530 ty::Predicate::RegionOutlives(ref pair) => pair.print(cx),
1531 ty::Predicate::TypeOutlives(ref pair) => pair.print(cx),
1532 ty::Predicate::Projection(ref pair) => pair.print(cx),
1533 ty::Predicate::WellFormed(ty) => ty.print(cx),
1534 ty::Predicate::ObjectSafe(trait_def_id) => {
1535 print!(cx, write("ObjectSafe({:?})", trait_def_id))
1537 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
1538 print!(cx, write("ClosureKind({:?}, {:?}, {:?})",
1539 closure_def_id, closure_substs, kind))
1541 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1542 print!(cx, write("ConstEvaluatable({:?}, {:?})", def_id, substs))
1550 ('tcx) Kind<'tcx>, (self, cx) {
1552 match self.unpack() {
1553 UnpackedKind::Lifetime(lt) => print!(cx, print(lt)),
1554 UnpackedKind::Type(ty) => print!(cx, print(ty)),
1555 UnpackedKind::Const(ct) => print!(cx, print(ct)),
1559 match self.unpack() {
1560 UnpackedKind::Lifetime(lt) => print!(cx, print(lt)),
1561 UnpackedKind::Type(ty) => print!(cx, print(ty)),
1562 UnpackedKind::Const(ct) => print!(cx, print(ct)),