1 use crate::hir::def::Namespace;
2 use crate::hir::def_id::DefId;
3 use crate::hir::map::definitions::DefPathData;
4 use crate::middle::region;
5 use crate::ty::subst::{self, Kind, Subst, SubstsRef, UnpackedKind};
6 use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed};
7 use crate::ty::{Bool, Char, Adt};
8 use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
9 use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
10 use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
11 use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
12 use crate::ty::{self, ParamConst, Ty, TypeFoldable};
13 use crate::ty::print::{FmtPrinter, PrintCx, Print};
14 use crate::mir::interpret::ConstValue;
21 use rustc_target::spec::abi::Abi;
22 use syntax::ast::CRATE_NODE_ID;
23 use syntax::symbol::{Symbol, InternedString};
26 /// The "region highlights" are used to control region printing during
27 /// specific error messages. When a "region highlight" is enabled, it
28 /// gives an alternate way to print specific regions. For now, we
29 /// always print those regions using a number, so something like "`'0`".
31 /// Regions not selected by the region highlight mode are presently
33 #[derive(Copy, Clone, Default)]
34 pub struct RegionHighlightMode {
35 /// If enabled, when we see the selected region, use "`'N`"
36 /// instead of the ordinary behavior.
37 highlight_regions: [Option<(ty::RegionKind, usize)>; 3],
39 /// If enabled, when printing a "free region" that originated from
40 /// the given `ty::BoundRegion`, print it as "`'1`". Free regions that would ordinarily
41 /// have names print as normal.
43 /// This is used when you have a signature like `fn foo(x: &u32,
44 /// y: &'a u32)` and we want to give a name to the region of the
46 highlight_bound_region: Option<(ty::BoundRegion, usize)>,
50 /// Mechanism for highlighting of specific regions for display in NLL region inference errors.
51 /// Contains region to highlight and counter for number to use when highlighting.
52 static REGION_HIGHLIGHT_MODE: Cell<RegionHighlightMode> =
53 Cell::new(RegionHighlightMode::default())
56 impl RegionHighlightMode {
57 /// Reads and returns the current region highlight settings (accesses thread-local state).
58 pub fn get() -> Self {
59 REGION_HIGHLIGHT_MODE.with(|c| c.get())
62 // Internal helper to update current settings during the execution of `op`.
66 op: impl FnOnce() -> R,
68 REGION_HIGHLIGHT_MODE.with(|c| {
76 /// If `region` and `number` are both `Some`, invokes
77 /// `highlighting_region`; otherwise, just invokes `op` directly.
78 pub fn maybe_highlighting_region<R>(
79 region: Option<ty::Region<'_>>,
80 number: Option<usize>,
81 op: impl FnOnce() -> R,
83 if let Some(k) = region {
84 if let Some(n) = number {
85 return Self::highlighting_region(k, n, op);
92 /// During the execution of `op`, highlights the region inference
93 /// variable `vid` as `'N`. We can only highlight one region `vid`
95 pub fn highlighting_region<R>(
96 region: ty::Region<'_>,
98 op: impl FnOnce() -> R,
100 let old_mode = Self::get();
101 let mut new_mode = old_mode;
102 let first_avail_slot = new_mode.highlight_regions.iter_mut()
103 .filter(|s| s.is_none())
107 "can only highlight {} placeholders at a time",
108 old_mode.highlight_regions.len(),
111 *first_avail_slot = Some((*region, number));
112 Self::set(old_mode, new_mode, op)
115 /// Convenience wrapper for `highlighting_region`.
116 pub fn highlighting_region_vid<R>(
119 op: impl FnOnce() -> R,
121 Self::highlighting_region(&ty::ReVar(vid), number, op)
124 /// Returns `Some(n)` with the number to use for the given region, if any.
125 fn region_highlighted(&self, region: ty::Region<'_>) -> Option<usize> {
129 .filter_map(|h| match h {
130 Some((r, n)) if r == region => Some(*n),
136 /// During the execution of `op`, highlight the given bound
137 /// region. We can only highlight one bound region at a time. See
138 /// the field `highlight_bound_region` for more detailed notes.
139 pub fn highlighting_bound_region<R>(
142 op: impl FnOnce() -> R,
144 let old_mode = Self::get();
145 assert!(old_mode.highlight_bound_region.is_none());
149 highlight_bound_region: Some((br, number)),
156 /// Returns `Some(N)` if the placeholder `p` is highlighted to print as "`'N`".
157 pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> {
158 self.region_highlighted(&ty::RePlaceholder(p))
162 macro_rules! gen_display_debug_body {
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 PrintCx::with(FmtPrinter { fmt: f }, |mut cx| {
166 $with(&cx.tcx.lift(self).expect("could not lift for printing"), &mut cx)
171 macro_rules! gen_display_debug {
172 ( ($($x:tt)+) $target:ty, display yes ) => {
173 impl<$($x)+> fmt::Display for $target {
174 gen_display_debug_body! { Print::print_display }
177 ( () $target:ty, display yes ) => {
178 impl fmt::Display for $target {
179 gen_display_debug_body! { Print::print_display }
182 ( ($($x:tt)+) $target:ty, debug yes ) => {
183 impl<$($x)+> fmt::Debug for $target {
184 gen_display_debug_body! { Print::print_debug }
187 ( () $target:ty, debug yes ) => {
188 impl fmt::Debug for $target {
189 gen_display_debug_body! { Print::print_debug }
192 ( $generic:tt $target:ty, $t:ident no ) => {};
194 macro_rules! gen_print_impl {
195 ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
196 impl<$($x)+, F: fmt::Write> Print<'tcx, FmtPrinter<F>> for $target {
197 type Output = fmt::Result;
198 fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter<F>>) -> fmt::Result {
204 ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
205 impl<F: fmt::Write> Print<'tcx, FmtPrinter<F>> for $target {
206 type Output = fmt::Result;
207 fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter<F>>) -> fmt::Result {
213 ( $generic:tt $target:ty,
214 $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => {
215 gen_print_impl! { $generic $target, $vars $disp $dbg }
216 gen_display_debug! { $generic $target, display $gendisp }
217 gen_display_debug! { $generic $target, debug $gendbg }
220 macro_rules! define_print {
221 ( $generic:tt $target:ty,
222 $vars:tt { display $disp:block debug $dbg:block } ) => {
223 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
225 ( $generic:tt $target:ty,
226 $vars:tt { debug $dbg:block display $disp:block } ) => {
227 gen_print_impl! { $generic $target, $vars yes $disp yes $dbg }
229 ( $generic:tt $target:ty,
230 $vars:tt { debug $dbg:block } ) => {
231 gen_print_impl! { $generic $target, $vars no {
232 bug!(concat!("display not implemented for ", stringify!($target)));
235 ( $generic:tt $target:ty,
236 ($self:ident, $cx:ident) { display $disp:block } ) => {
237 gen_print_impl! { $generic $target, ($self, $cx) yes $disp no {
238 write!($cx.printer.fmt, "{:?}", $self)
242 macro_rules! define_print_multi {
243 ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => {
244 $(define_print! { $generic $target, $vars $def })*
247 macro_rules! print_inner {
248 ( $cx:expr, write ($($data:expr),+) ) => {
249 write!($cx.printer.fmt, $($data),+)
251 ( $cx:expr, $kind:ident ($data:expr) ) => {
256 ( $cx:expr $(, $kind:ident $data:tt)+ ) => {
257 Ok(())$(.and_then(|_| print_inner!($cx, $kind $data)))+
261 impl<F: fmt::Write> PrintCx<'a, 'gcx, 'tcx, FmtPrinter<F>> {
268 print!(self, write("("))?;
269 let mut inputs = inputs.iter();
270 if let Some(&ty) = inputs.next() {
271 print!(self, print_display(ty))?;
273 print!(self, write(", "), print_display(ty))?;
276 print!(self, write(", ..."))?;
279 print!(self, write(")"))?;
280 if !output.is_unit() {
281 print!(self, write(" -> "), print_display(output))?;
290 substs: SubstsRef<'tcx>,
292 projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
294 let key = self.tcx.def_key(def_id);
295 let generics = self.tcx.generics_of(def_id);
297 if let Some(parent_def_id) = generics.parent {
298 assert_eq!(parent_def_id, DefId { index: key.parent.unwrap(), ..def_id });
300 let parent_generics = self.tcx.generics_of(parent_def_id);
301 let parent_has_own_self =
302 parent_generics.has_self && parent_generics.parent_count == 0;
303 if parent_has_own_self {
304 print!(self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
305 self.parameterized(parent_def_id, substs, Namespace::TypeNS, iter::empty())?;
306 print!(self, write(">"))?;
308 self.parameterized(parent_def_id, substs, ns, iter::empty())?;
311 // Skip `::{{constructor}}` on tuple/unit structs.
312 match key.disambiguated_data.data {
313 DefPathData::StructCtor => {}
316 print!(self, write("::{}", key.disambiguated_data.data.as_interned_str()))?;
320 // FIXME(eddyb) recurse through printing a path via `self`, instead
321 // instead of using the `tcx` method that produces a `String`.
322 print!(self, write("{}",
323 self.tcx.def_path_str_with_substs_and_ns(def_id, Some(substs), ns)))?;
325 // For impls, the above call already prints relevant generics args.
326 if let DefPathData::Impl = key.disambiguated_data.data {
331 let mut empty = true;
332 let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
335 print!(cx, write("{}", start))
337 print!(cx, write("{}", cont))
341 let start = if ns == Namespace::ValueNS { "::<" } else { "<" };
343 let has_own_self = generics.has_self && generics.parent_count == 0;
344 let params = &generics.params[has_own_self as usize..];
346 // Don't print any regions if they're all erased.
347 let print_regions = params.iter().any(|param| {
348 match substs[param.index as usize].unpack() {
349 UnpackedKind::Lifetime(r) => *r != ty::ReErased,
354 // Don't print args that are the defaults of their respective parameters.
355 let num_supplied_defaults = if self.is_verbose {
358 params.iter().rev().take_while(|param| {
360 ty::GenericParamDefKind::Lifetime => false,
361 ty::GenericParamDefKind::Type { has_default, .. } => {
362 has_default && substs[param.index as usize] == Kind::from(
363 self.tcx.type_of(param.def_id).subst(self.tcx, substs)
366 ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
371 for param in ¶ms[..params.len() - num_supplied_defaults] {
372 match substs[param.index as usize].unpack() {
373 UnpackedKind::Lifetime(region) => {
377 start_or_continue(self, start, ", ")?;
378 if !region.display_outputs_anything(self) {
379 // This happens when the value of the region
380 // parameter is not easily serialized. This may be
381 // because the user omitted it in the first place,
382 // or because it refers to some block in the code,
383 // etc. I'm not sure how best to serialize this.
384 print!(self, write("'_"))?;
386 region.print_display(self)?;
389 UnpackedKind::Type(ty) => {
390 start_or_continue(self, start, ", ")?;
391 ty.print_display(self)?;
393 UnpackedKind::Const(ct) => {
394 start_or_continue(self, start, ", ")?;
395 ct.print_display(self)?;
400 for projection in projections {
401 start_or_continue(self, start, ", ")?;
404 self.tcx.associated_item(projection.item_def_id).ident),
405 print_display(projection.ty))?;
408 start_or_continue(self, "", ">")
411 fn in_binder<T>(&mut self, value: &ty::Binder<T>) -> fmt::Result
412 where T: Print<'tcx, FmtPrinter<F>, Output = fmt::Result> + TypeFoldable<'tcx>
414 fn name_by_region_index(index: usize) -> InternedString {
416 0 => Symbol::intern("'r"),
417 1 => Symbol::intern("'s"),
418 i => Symbol::intern(&format!("'t{}", i-2)),
422 // Replace any anonymous late-bound regions with named
423 // variants, using gensym'd identifiers, so that we can
424 // clearly differentiate between named and unnamed regions in
425 // the output. We'll probably want to tweak this over time to
426 // decide just how much information to give.
427 if self.binder_depth == 0 {
428 self.prepare_late_bound_region_info(value);
431 let mut empty = true;
432 let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
435 print!(cx, write("{}", start))
437 print!(cx, write("{}", cont))
441 let old_region_index = self.region_index;
442 let mut region_index = old_region_index;
443 let new_value = self.tcx.replace_late_bound_regions(value, |br| {
444 let _ = start_or_continue(self, "for<", ", ");
446 ty::BrNamed(_, name) => {
447 let _ = print!(self, write("{}", name));
454 let name = name_by_region_index(region_index);
456 if !self.is_name_used(&name) {
460 let _ = print!(self, write("{}", name));
461 ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name)
464 self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br))
466 start_or_continue(self, "", "> ")?;
468 // Push current state to gcx, and restore after writing new_value.
469 self.binder_depth += 1;
470 self.region_index = region_index;
471 let result = new_value.print_display(self);
472 self.region_index = old_region_index;
473 self.binder_depth -= 1;
477 fn is_name_used(&self, name: &InternedString) -> bool {
478 match self.used_region_names {
479 Some(ref names) => names.contains(name),
485 pub fn parameterized<F: fmt::Write>(
488 substs: SubstsRef<'_>,
491 PrintCx::with(FmtPrinter { fmt: f }, |mut cx| {
492 let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
493 cx.parameterized(did, substs, ns, iter::empty())
497 impl<'a, 'tcx, P, T: Print<'tcx, P>> Print<'tcx, P> for &'a T {
498 type Output = T::Output;
499 fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output {
505 ('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, cx) {
507 // Generate the main trait ref, including associated types.
508 let mut first = true;
510 if let Some(principal) = self.principal() {
511 let mut resugared_principal = false;
513 // Special-case `Fn(...) -> ...` and resugar it.
514 if !cx.is_verbose && cx.tcx.lang_items().fn_trait_kind(principal.def_id).is_some() {
515 if let Tuple(ref args) = principal.substs.type_at(0).sty {
516 let mut projections = self.projection_bounds();
517 if let (Some(proj), None) = (projections.next(), projections.next()) {
518 print!(cx, write("{}", cx.tcx.def_path_str(principal.def_id)))?;
519 cx.fn_sig(args, false, proj.ty)?;
520 resugared_principal = true;
525 if !resugared_principal {
526 // Use a type that can't appear in defaults of type parameters.
527 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
528 let principal = principal.with_self_ty(cx.tcx, dummy_self);
533 self.projection_bounds(),
540 let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
541 cx.tcx.def_path_str(did)
544 // The auto traits come ordered by `DefPathHash`. While
545 // `DefPathHash` is *stable* in the sense that it depends on
546 // neither the host nor the phase of the moon, it depends
547 // "pseudorandomly" on the compiler version and the target.
549 // To avoid that causing instabilities in compiletest
550 // output, sort the auto-traits alphabetically.
553 for auto_trait in auto_traits {
555 print!(cx, write(" + "))?;
559 print!(cx, write("{}", auto_trait))?;
567 impl fmt::Debug for ty::GenericParamDef {
568 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569 let type_name = match self.kind {
570 ty::GenericParamDefKind::Lifetime => "Lifetime",
571 ty::GenericParamDefKind::Type { .. } => "Type",
572 ty::GenericParamDefKind::Const => "Const",
574 write!(f, "{}({}, {:?}, {})",
582 impl fmt::Debug for ty::TraitDef {
583 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584 PrintCx::with(FmtPrinter { fmt: f }, |cx| {
585 print!(cx, write("{}", cx.tcx.def_path_str(self.def_id)))
590 impl fmt::Debug for ty::AdtDef {
591 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
592 PrintCx::with(FmtPrinter { fmt: f }, |cx| {
593 print!(cx, write("{}", cx.tcx.def_path_str(self.did)))
598 impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> {
599 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600 write!(f, "ClosureUpvar({:?},{:?})",
606 impl fmt::Debug for ty::UpvarId {
607 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
608 PrintCx::with(FmtPrinter { fmt: f }, |cx| {
609 print!(cx, write("UpvarId({:?};`{}`;{:?})",
610 self.var_path.hir_id,
611 cx.tcx.hir().name_by_hir_id(self.var_path.hir_id),
612 self.closure_expr_id))
617 impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> {
618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
619 write!(f, "UpvarBorrow({:?}, {:?})",
620 self.kind, self.region)
625 ('tcx) &'tcx ty::List<Ty<'tcx>>, (self, cx) {
627 print!(cx, write("{{"))?;
628 let mut tys = self.iter();
629 if let Some(&ty) = tys.next() {
630 print!(cx, print(ty))?;
632 print!(cx, write(", "), print(ty))?;
635 print!(cx, write("}}"))
641 ('tcx) ty::TypeAndMut<'tcx>, (self, cx) {
644 write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }),
651 ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) {
653 let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
655 let trait_ref = *ty::Binder::bind(*self)
656 .with_self_ty(cx.tcx, dummy_self)
658 cx.parameterized(trait_ref.def_id, trait_ref.substs, Namespace::TypeNS, iter::empty())
661 self.print_display(cx)
667 ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) {
669 print!(cx, write("{:?} -> ", self.kind), print(self.target))
675 () ty::BoundRegion, (self, cx) {
678 return self.print_debug(cx);
681 if let BrNamed(_, name) = *self {
682 if name != "" && name != "'_" {
683 return print!(cx, write("{}", name));
687 let highlight = RegionHighlightMode::get();
688 if let Some((region, counter)) = highlight.highlight_bound_region {
690 return print!(cx, write("'{}", counter));
698 BrAnon(n) => print!(cx, write("BrAnon({:?})", n)),
699 BrFresh(n) => print!(cx, write("BrFresh({:?})", n)),
700 BrNamed(did, name) => {
701 print!(cx, write("BrNamed({:?}:{:?}, {})",
702 did.krate, did.index, name))
704 BrEnv => print!(cx, write("BrEnv")),
710 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
712 // NB: this must be kept in sync with the printing logic above.
713 impl ty::BoundRegion {
714 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
719 if let BrNamed(_, name) = *self {
720 if name != "" && name != "'_" {
725 let highlight = RegionHighlightMode::get();
726 if let Some((region, _)) = highlight.highlight_bound_region {
737 () ty::PlaceholderRegion, (self, cx) {
740 return self.print_debug(cx);
743 let highlight = RegionHighlightMode::get();
744 if let Some(counter) = highlight.placeholder_highlight(*self) {
745 return print!(cx, write("'{}", counter));
748 print!(cx, print_display(self.name))
753 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
755 // NB: this must be kept in sync with the printing logic above.
756 impl ty::PlaceholderRegion {
757 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
762 let highlight = RegionHighlightMode::get();
763 if highlight.placeholder_highlight(*self).is_some() {
767 self.name.display_outputs_anything(cx)
772 () ty::RegionKind, (self, cx) {
775 return self.print_debug(cx);
778 // Watch out for region highlights.
779 if let Some(n) = RegionHighlightMode::get().region_highlighted(self) {
780 return print!(cx, write("'{:?}", n));
783 // These printouts are concise. They do not contain all the information
784 // the user might want to diagnose an error, but there is basically no way
785 // to fit that into a short string. Hence the recommendation to use
786 // `explain_region()` or `note_and_explain_region()`.
788 ty::ReEarlyBound(ref data) => {
789 if data.name != "'_" {
790 print!(cx, write("{}", data.name))
795 ty::ReLateBound(_, br) |
796 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
797 print!(cx, print_display(br))
799 ty::RePlaceholder(p) => {
800 print!(cx, print_display(p))
802 ty::ReScope(scope) if cx.identify_regions => {
804 region::ScopeData::Node =>
805 print!(cx, write("'{}s", scope.item_local_id().as_usize())),
806 region::ScopeData::CallSite =>
807 print!(cx, write("'{}cs", scope.item_local_id().as_usize())),
808 region::ScopeData::Arguments =>
809 print!(cx, write("'{}as", scope.item_local_id().as_usize())),
810 region::ScopeData::Destruction =>
811 print!(cx, write("'{}ds", scope.item_local_id().as_usize())),
812 region::ScopeData::Remainder(first_statement_index) => print!(cx, write(
814 scope.item_local_id().as_usize(),
815 first_statement_index.index()
819 ty::ReVar(region_vid) if cx.identify_regions => {
820 print!(cx, print_debug(region_vid))
822 ty::ReVar(region_vid) => {
823 print!(cx, print_display(region_vid))
826 ty::ReErased => Ok(()),
827 ty::ReStatic => print!(cx, write("'static")),
828 ty::ReEmpty => print!(cx, write("'<empty>")),
830 // The user should never encounter these in unsubstituted form.
831 ty::ReClosureBound(vid) => print!(cx, write("{:?}", vid)),
836 ty::ReEarlyBound(ref data) => {
837 print!(cx, write("ReEarlyBound({}, {})",
842 ty::ReClosureBound(ref vid) => {
843 print!(cx, write("ReClosureBound({:?})",
847 ty::ReLateBound(binder_id, ref bound_region) => {
848 print!(cx, write("ReLateBound({:?}, {:?})",
853 ty::ReFree(ref fr) => print!(cx, write("{:?}", fr)),
856 print!(cx, write("ReScope({:?})", id))
859 ty::ReStatic => print!(cx, write("ReStatic")),
861 ty::ReVar(ref vid) => {
862 print!(cx, write("{:?}", vid))
865 ty::RePlaceholder(placeholder) => {
866 print!(cx, write("RePlaceholder({:?})", placeholder))
869 ty::ReEmpty => print!(cx, write("ReEmpty")),
871 ty::ReErased => print!(cx, write("ReErased"))
877 // HACK(eddyb) Trying to print a lifetime might not print anything, which
878 // may need special handling in the caller (of `ty::RegionKind::print`).
879 // To avoid printing to a temporary string, the `display_outputs_anything`
880 // method can instead be used to determine this, ahead of time.
882 // NB: this must be kept in sync with the printing logic above.
883 impl ty::RegionKind {
884 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
889 if RegionHighlightMode::get().region_highlighted(self).is_some() {
894 ty::ReEarlyBound(ref data) => {
895 data.name != "" && data.name != "'_"
898 ty::ReLateBound(_, br) |
899 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => {
900 br.display_outputs_anything(cx)
903 ty::RePlaceholder(p) => p.display_outputs_anything(cx),
906 ty::ReVar(_) if cx.identify_regions => true,
908 ty::ReVar(region_vid) => region_vid.display_outputs_anything(cx),
911 ty::ReErased => false,
915 ty::ReClosureBound(_) => true,
921 () ty::FreeRegion, (self, cx) {
923 print!(cx, write("ReFree({:?}, {:?})", self.scope, self.bound_region))
929 () ty::Variance, (self, cx) {
931 cx.printer.fmt.write_str(match *self {
932 ty::Covariant => "+",
933 ty::Contravariant => "-",
934 ty::Invariant => "o",
935 ty::Bivariant => "*",
942 ('tcx) ty::FnSig<'tcx>, (self, cx) {
944 if self.unsafety == hir::Unsafety::Unsafe {
945 print!(cx, write("unsafe "))?;
948 if self.abi != Abi::Rust {
949 print!(cx, write("extern {} ", self.abi))?;
952 print!(cx, write("fn"))?;
953 cx.fn_sig(self.inputs(), self.c_variadic, self.output())
956 print!(cx, write("({:?}; c_variadic: {})->{:?}",
957 self.inputs(), self.c_variadic, self.output()))
962 impl fmt::Debug for ty::TyVid {
963 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
964 write!(f, "_#{}t", self.index)
968 impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
969 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
970 write!(f, "_#{}f", self.index)
974 impl fmt::Debug for ty::IntVid {
975 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
976 write!(f, "_#{}i", self.index)
980 impl fmt::Debug for ty::FloatVid {
981 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
982 write!(f, "_#{}f", self.index)
987 () ty::RegionVid, (self, cx) {
990 return self.print_debug(cx);
993 let highlight = RegionHighlightMode::get();
994 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
995 return print!(cx, write("'{:?}", counter));
1001 // HACK(eddyb) this is duplicated from `display` printing,
1002 // to keep NLL borrowck working even with `-Zverbose`.
1003 let highlight = RegionHighlightMode::get();
1004 if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) {
1005 return print!(cx, write("'{:?}", counter));
1008 print!(cx, write("'_#{}r", self.index()))
1013 // HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`)
1015 // NB: this must be kept in sync with the printing logic above.
1016 impl ty::RegionVid {
1017 fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
1022 let highlight = RegionHighlightMode::get();
1023 if highlight.region_highlighted(&ty::ReVar(*self)).is_some() {
1032 () ty::InferTy, (self, cx) {
1035 return self.print_debug(cx);
1038 ty::TyVar(_) => print!(cx, write("_")),
1039 ty::IntVar(_) => print!(cx, write("{}", "{integer}")),
1040 ty::FloatVar(_) => print!(cx, write("{}", "{float}")),
1041 ty::FreshTy(v) => print!(cx, write("FreshTy({})", v)),
1042 ty::FreshIntTy(v) => print!(cx, write("FreshIntTy({})", v)),
1043 ty::FreshFloatTy(v) => print!(cx, write("FreshFloatTy({})", v))
1048 ty::TyVar(ref v) => print!(cx, write("{:?}", v)),
1049 ty::IntVar(ref v) => print!(cx, write("{:?}", v)),
1050 ty::FloatVar(ref v) => print!(cx, write("{:?}", v)),
1051 ty::FreshTy(v) => print!(cx, write("FreshTy({:?})", v)),
1052 ty::FreshIntTy(v) => print!(cx, write("FreshIntTy({:?})", v)),
1053 ty::FreshFloatTy(v) => print!(cx, write("FreshFloatTy({:?})", v))
1059 impl fmt::Debug for ty::IntVarValue {
1060 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1062 ty::IntType(ref v) => v.fmt(f),
1063 ty::UintType(ref v) => v.fmt(f),
1068 impl fmt::Debug for ty::FloatVarValue {
1069 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1074 // The generic impl doesn't work yet because projections are not
1075 // normalized under HRTB.
1076 /*impl<T> fmt::Display for ty::Binder<T>
1077 where T: fmt::Display + for<'a> ty::Lift<'a>,
1078 for<'a> <T as ty::Lift<'a>>::Lifted: fmt::Display + TypeFoldable<'a>
1080 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1081 PrintCx::with(|cx| cx.in_binder(cx.tcx.lift(self)
1082 .expect("could not lift for printing")))
1086 define_print_multi! {
1088 ('tcx) ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
1089 ('tcx) ty::Binder<ty::TraitRef<'tcx>>,
1090 ('tcx) ty::Binder<ty::FnSig<'tcx>>,
1091 ('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
1092 ('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
1093 ('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
1094 ('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
1095 ('tcx) ty::Binder<ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>>
1105 ('tcx) ty::TraitRef<'tcx>, (self, cx) {
1107 cx.parameterized(self.def_id, self.substs, Namespace::TypeNS, iter::empty())
1112 print(self.self_ty()),
1114 print_display(self),
1122 ('tcx) ty::Ty<'tcx>, (self, cx) {
1125 Bool => print!(cx, write("bool")),
1126 Char => print!(cx, write("char")),
1127 Int(t) => print!(cx, write("{}", t.ty_to_string())),
1128 Uint(t) => print!(cx, write("{}", t.ty_to_string())),
1129 Float(t) => print!(cx, write("{}", t.ty_to_string())),
1131 print!(cx, write("*{} ", match tm.mutbl {
1132 hir::MutMutable => "mut",
1133 hir::MutImmutable => "const",
1137 Ref(r, ty, mutbl) => {
1138 print!(cx, write("&"))?;
1139 if r.display_outputs_anything(cx) {
1140 print!(cx, print_display(r), write(" "))?;
1142 ty::TypeAndMut { ty, mutbl }.print(cx)
1144 Never => print!(cx, write("!")),
1146 print!(cx, write("("))?;
1147 let mut tys = tys.iter();
1148 if let Some(&ty) = tys.next() {
1149 print!(cx, print(ty), write(","))?;
1150 if let Some(&ty) = tys.next() {
1151 print!(cx, write(" "), print(ty))?;
1153 print!(cx, write(", "), print(ty))?;
1157 print!(cx, write(")"))
1159 FnDef(def_id, substs) => {
1160 let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs);
1161 print!(cx, print(sig), write(" {{"))?;
1162 cx.parameterized(def_id, substs, Namespace::ValueNS, iter::empty())?;
1163 print!(cx, write("}}"))
1165 FnPtr(ref bare_fn) => {
1168 Infer(infer_ty) => print!(cx, write("{}", infer_ty)),
1169 Error => print!(cx, write("[type error]")),
1170 Param(ref param_ty) => print!(cx, write("{}", param_ty)),
1171 Bound(debruijn, bound_ty) => {
1172 match bound_ty.kind {
1173 ty::BoundTyKind::Anon => {
1174 if debruijn == ty::INNERMOST {
1175 print!(cx, write("^{}", bound_ty.var.index()))
1177 print!(cx, write("^{}_{}", debruijn.index(), bound_ty.var.index()))
1181 ty::BoundTyKind::Param(p) => print!(cx, write("{}", p)),
1184 Adt(def, substs) => {
1185 cx.parameterized(def.did, substs, Namespace::TypeNS, iter::empty())
1187 Dynamic(data, r) => {
1188 let print_r = r.display_outputs_anything(cx);
1190 print!(cx, write("("))?;
1192 print!(cx, write("dyn "))?;
1195 print!(cx, write(" + "), print_display(r), write(")"))?;
1199 Foreign(def_id) => {
1202 subst::InternalSubsts::empty(),
1207 Projection(ref data) => data.print(cx),
1208 UnnormalizedProjection(ref data) => {
1209 print!(cx, write("Unnormalized("))?;
1211 print!(cx, write(")"))
1213 Placeholder(placeholder) => {
1214 print!(cx, write("Placeholder({:?})", placeholder))
1216 Opaque(def_id, substs) => {
1218 return print!(cx, write("Opaque({:?}, {:?})", def_id, substs));
1221 let def_key = cx.tcx.def_key(def_id);
1222 if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
1223 print!(cx, write("{}", name))?;
1224 let mut substs = substs.iter();
1225 // FIXME(eddyb) print this with `parameterized`.
1226 if let Some(first) = substs.next() {
1227 print!(cx, write("::<"))?;
1228 print!(cx, write("{}", first))?;
1229 for subst in substs {
1230 print!(cx, write(", {}", subst))?;
1232 print!(cx, write(">"))?;
1236 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
1237 // by looking up the projections associated with the def_id.
1238 let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs);
1240 let mut first = true;
1241 let mut is_sized = false;
1242 print!(cx, write("impl"))?;
1243 for predicate in bounds.predicates {
1244 if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
1245 // Don't print +Sized, but rather +?Sized if absent.
1246 if Some(trait_ref.def_id()) == cx.tcx.lang_items().sized_trait() {
1252 write("{}", if first { " " } else { "+" }),
1258 print!(cx, write("{}?Sized", if first { " " } else { "+" }))?;
1260 print!(cx, write(" Sized"))?;
1264 Str => print!(cx, write("str")),
1265 Generator(did, substs, movability) => {
1266 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1267 let witness = substs.witness(did, cx.tcx);
1268 if movability == hir::GeneratorMovability::Movable {
1269 print!(cx, write("[generator"))?;
1271 print!(cx, write("[static generator"))?;
1274 // FIXME(eddyb) should use `def_span`.
1275 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1276 print!(cx, write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?;
1278 cx.tcx.with_freevars(hir_id, |freevars| {
1279 for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1283 cx.tcx.hir().name(freevar.var_id())),
1290 // cross-crate closure types should only be
1291 // visible in codegen bug reports, I imagine.
1292 print!(cx, write("@{:?}", did))?;
1294 for (index, upvar_ty) in upvar_tys.enumerate() {
1296 write("{}{}:", sep, index),
1302 print!(cx, write(" "), print(witness), write("]"))
1304 GeneratorWitness(types) => {
1305 cx.in_binder(&types)
1307 Closure(did, substs) => {
1308 let upvar_tys = substs.upvar_tys(did, cx.tcx);
1309 print!(cx, write("[closure"))?;
1311 // FIXME(eddyb) should use `def_span`.
1312 if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) {
1313 if cx.tcx.sess.opts.debugging_opts.span_free_formats {
1314 print!(cx, write("@{:?}", hir_id))?;
1316 print!(cx, write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?;
1319 cx.tcx.with_freevars(hir_id, |freevars| {
1320 for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) {
1324 cx.tcx.hir().name(freevar.var_id())),
1331 // cross-crate closure types should only be
1332 // visible in codegen bug reports, I imagine.
1333 print!(cx, write("@{:?}", did))?;
1335 for (index, upvar_ty) in upvar_tys.enumerate() {
1337 write("{}{}:", sep, index),
1345 " closure_kind_ty={:?} closure_sig_ty={:?}",
1346 substs.closure_kind_ty(did, cx.tcx),
1347 substs.closure_sig_ty(did, cx.tcx)
1351 print!(cx, write("]"))
1354 print!(cx, write("["), print(ty), write("; "))?;
1356 ty::LazyConst::Unevaluated(_def_id, _substs) => {
1357 print!(cx, write("_"))?;
1359 ty::LazyConst::Evaluated(c) => {
1361 ConstValue::Infer(..) => print!(cx, write("_"))?,
1362 ConstValue::Param(ParamConst { name, .. }) =>
1363 print!(cx, write("{}", name))?,
1364 _ => print!(cx, write("{}", c.unwrap_usize(cx.tcx)))?,
1368 print!(cx, write("]"))
1371 print!(cx, write("["), print(ty), write("]"))
1376 self.print_display(cx)
1382 ('tcx) ConstValue<'tcx>, (self, cx) {
1385 ConstValue::Infer(..) => print!(cx, write("_")),
1386 ConstValue::Param(ParamConst { name, .. }) => print!(cx, write("{}", name)),
1387 _ => print!(cx, write("{:?}", self)),
1394 ('tcx) ty::Const<'tcx>, (self, cx) {
1396 print!(cx, write("{} : {}", self.val, self.ty))
1402 ('tcx) ty::LazyConst<'tcx>, (self, cx) {
1405 // FIXME(const_generics) this should print at least the type.
1406 ty::LazyConst::Unevaluated(..) => print!(cx, write("_ : _")),
1407 ty::LazyConst::Evaluated(c) => print!(cx, write("{}", c)),
1414 () ty::ParamTy, (self, cx) {
1416 print!(cx, write("{}", self.name))
1419 print!(cx, write("{}/#{}", self.name, self.idx))
1425 () ty::ParamConst, (self, cx) {
1427 print!(cx, write("{}", self.name))
1430 print!(cx, write("{}/#{}", self.name, self.index))
1435 // Similar problem to `Binder<T>`, can't define a generic impl.
1436 define_print_multi! {
1438 ('tcx) ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
1439 ('tcx) ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
1443 print!(cx, print(self.0), write(" : "), print(self.1))
1449 ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) {
1451 print!(cx, print(self.a), write(" <: "), print(self.b))
1457 ('tcx) ty::TraitPredicate<'tcx>, (self, cx) {
1459 print!(cx, write("TraitPredicate({:?})",
1463 print!(cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref))
1469 ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) {
1472 write("ProjectionPredicate("),
1473 print(self.projection_ty),
1479 print!(cx, print(self.projection_ty), write(" == "), print(self.ty))
1485 ('tcx) ty::ProjectionTy<'tcx>, (self, cx) {
1487 cx.parameterized(self.item_def_id, self.substs, Namespace::TypeNS, iter::empty())
1493 () ty::ClosureKind, (self, cx) {
1496 ty::ClosureKind::Fn => print!(cx, write("Fn")),
1497 ty::ClosureKind::FnMut => print!(cx, write("FnMut")),
1498 ty::ClosureKind::FnOnce => print!(cx, write("FnOnce")),
1505 ('tcx) ty::Predicate<'tcx>, (self, cx) {
1508 ty::Predicate::Trait(ref data) => data.print(cx),
1509 ty::Predicate::Subtype(ref predicate) => predicate.print(cx),
1510 ty::Predicate::RegionOutlives(ref predicate) => predicate.print(cx),
1511 ty::Predicate::TypeOutlives(ref predicate) => predicate.print(cx),
1512 ty::Predicate::Projection(ref predicate) => predicate.print(cx),
1513 ty::Predicate::WellFormed(ty) => print!(cx, print(ty), write(" well-formed")),
1514 ty::Predicate::ObjectSafe(trait_def_id) => {
1515 print!(cx, write("the trait `{}` is object-safe",
1516 cx.tcx.def_path_str(trait_def_id)))
1518 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
1519 print!(cx, write("the closure `{}` implements the trait `{}`",
1520 cx.tcx.def_path_str(closure_def_id), kind))
1522 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1523 print!(cx, write("the constant `"))?;
1524 cx.parameterized(def_id, substs, Namespace::ValueNS, iter::empty())?;
1525 print!(cx, write("` can be evaluated"))
1531 ty::Predicate::Trait(ref a) => a.print(cx),
1532 ty::Predicate::Subtype(ref pair) => pair.print(cx),
1533 ty::Predicate::RegionOutlives(ref pair) => pair.print(cx),
1534 ty::Predicate::TypeOutlives(ref pair) => pair.print(cx),
1535 ty::Predicate::Projection(ref pair) => pair.print(cx),
1536 ty::Predicate::WellFormed(ty) => ty.print(cx),
1537 ty::Predicate::ObjectSafe(trait_def_id) => {
1538 print!(cx, write("ObjectSafe({:?})", trait_def_id))
1540 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
1541 print!(cx, write("ClosureKind({:?}, {:?}, {:?})",
1542 closure_def_id, closure_substs, kind))
1544 ty::Predicate::ConstEvaluatable(def_id, substs) => {
1545 print!(cx, write("ConstEvaluatable({:?}, {:?})", def_id, substs))
1553 ('tcx) Kind<'tcx>, (self, cx) {
1555 match self.unpack() {
1556 UnpackedKind::Lifetime(lt) => print!(cx, print(lt)),
1557 UnpackedKind::Type(ty) => print!(cx, print(ty)),
1558 UnpackedKind::Const(ct) => print!(cx, print(ct)),
1562 match self.unpack() {
1563 UnpackedKind::Lifetime(lt) => print!(cx, print(lt)),
1564 UnpackedKind::Type(ty) => print!(cx, print(ty)),
1565 UnpackedKind::Const(ct) => print!(cx, print(ct)),