mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-31 17:12:53 +00:00
Auto merge of #112984 - BoxyUwU:debug_with_infcx, r=compiler-errors
Introduce `trait DebugWithInfcx` to debug format types with universe info Seeing universes of infer vars is valuable for debugging but currently we have no way of easily debug formatting a type with the universes of all the infer vars shown. In the future I hope to augment the new solver's proof tree output with a `DebugWithInfcx` impl so that it can show universes but I left that out of this PR as it would be non trivial and this is already large and complex enough. The goal here is to make the various abstractions taking `T: Debug` able to use the codepath for printing out universes, that way we can do `debug!("{:?}", my_x)` and have `my_x` have universes shown, same for the `write!` macro. It's not possible to put the `Infcx: InferCtxtLike<I>` into the formatter argument to `Debug::fmt` so it has to go into the self ty. For this we introduce the type `OptWithInfcx<I: Interner, Infcx: InferCtxtLike<I>, T>` which has the data `T` optionally coupled with the infcx (more on why it's optional later). Because of coherence/orphan rules it's not possible to write the impl `Debug for OptWithInfcx<..., MyType>` when `OptWithInfcx` is in a upstream crate. This necessitates a blanket impl in the crate defining `OptWithInfcx` like so: `impl<T: DebugWithInfcx> Debug for OptWithInfcx<..., T>`. It is not intended for people to manually call `DebugWithInfcx::fmt`, the `Debug` impl for `OptWithInfcx` should be preferred. The infcx has to be optional in `OptWithInfcx` as otherwise we would end up with a large amount of code duplication. Almost all types that want to be used with `OptWithInfcx` do not themselves need access to the infcx so if we were to not optional we would end up with large `Debug` and `DebugWithInfcx` impls that were practically identical other than that when formatting their fields we wrap the field in `OptWithInfcx` instead of formatting it alone. The only types that need access to the infcx themselves are ty/const/region infer vars, everything else is implemented by having the `Debug` impl defer to `OptWithInfcx` with no infcx available. The `DebugWithInfcx` impl is pretty much just the standard `Debug` impl except that instead of recursively formatting fields with `write!(f, "{x:?}")` we must do `write!(f, "{:?}", opt_infcx.wrap(x))`. This is some pretty rough boilerplate but I could not think of an alternative unfortunately. `OptWithInfcx::wrap` is an eager `Option::map` because 99% of callsites were discarding the existing data in `OptWithInfcx` and did not need lazy evaluation. A trait `InferCtxtLike` was added instead of using `InferCtxt<'tcx>` as we need to implement `DebugWithInfcx` for types living in `rustc_type_ir` which are generic over an interner and do not have access to `InferCtxt` since it lives in `rustc_infer`. Additionally I suspect that adding universe info to new solver proof tree output will require an implementation of `InferCtxtLike` for something that is not an `InferCtxt` although this is not the primary motivaton. --- To summarize: - There is a type `OptWithInfcx` which bundles some data optionally with an infcx with allows us to pass an infcx into a `Debug` impl. It's optional instead of being there unconditionally so that we can share code for `Debug` and `DebugWithInfcx` impls that don't care about whether there is an infcx available but have fields that might care. - There is a trait `DebugWithInfcx` which allows downstream crates to add impls of the form `Debug for OptWithInfcx<...>` which would normally be forbidden by orphan rules/coherence. - There is a trait `InferCtxtLike` to allow us to implement `DebugWithInfcx` for types that live in `rustc_type_ir` This allows debug formatting various `ty::*` structures with universes shown by using the `Debug` impl for `OptWithInfcx::new(ty, infcx)` --- This PR does not add `DebugWithInfcx` impls to absolutely _everything_ that should realistically have them, for example you cannot use `OptWithInfcx<Obligation<Predicate>>`. I am leaving this to a future PR to do so as it would likely be a lot more work to do.
This commit is contained in:
commit
993deaa0bf
@ -332,6 +332,39 @@ pub struct InferCtxt<'tcx> {
|
||||
next_trait_solver: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> ty::InferCtxtLike<TyCtxt<'tcx>> for InferCtxt<'tcx> {
|
||||
fn universe_of_ty(&self, ty: ty::InferTy) -> Option<ty::UniverseIndex> {
|
||||
use InferTy::*;
|
||||
match ty {
|
||||
// FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
|
||||
// ty infers will give you the universe of the var it resolved to not the universe
|
||||
// it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
|
||||
// try to print out `?0.1` it will just print `?0`.
|
||||
TyVar(ty_vid) => match self.probe_ty_var(ty_vid) {
|
||||
Err(universe) => Some(universe),
|
||||
Ok(_) => None,
|
||||
},
|
||||
IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn universe_of_ct(&self, ct: ty::InferConst<'tcx>) -> Option<ty::UniverseIndex> {
|
||||
use ty::InferConst::*;
|
||||
match ct {
|
||||
// Same issue as with `universe_of_ty`
|
||||
Var(ct_vid) => match self.probe_const_var(ct_vid) {
|
||||
Err(universe) => Some(universe),
|
||||
Ok(_) => None,
|
||||
},
|
||||
Fresh(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
|
||||
Some(self.universe_of_region_vid(lt))
|
||||
}
|
||||
}
|
||||
|
||||
/// See the `error_reporting` module for more details.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
|
||||
pub enum ValuePairs<'tcx> {
|
||||
@ -1068,6 +1101,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().universe(r)
|
||||
}
|
||||
|
||||
/// Return the universe that the region variable `r` was created in.
|
||||
pub fn universe_of_region_vid(&self, vid: ty::RegionVid) -> ty::UniverseIndex {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().var_universe(vid)
|
||||
}
|
||||
|
||||
/// Number of region variables created so far.
|
||||
pub fn num_region_vars(&self) -> usize {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
|
||||
|
@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::HashStable;
|
||||
|
||||
/// An unevaluated (potentially generic) constant used in the type-system.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
|
||||
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct UnevaluatedConst<'tcx> {
|
||||
pub def: DefId,
|
||||
@ -35,7 +35,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
||||
pub enum Expr<'tcx> {
|
||||
Binop(mir::BinOp, Const<'tcx>, Const<'tcx>),
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::arena::Arena;
|
||||
use rustc_data_structures::aligned::{align_of, Aligned};
|
||||
use rustc_serialize::{Encodable, Encoder};
|
||||
use rustc_type_ir::{InferCtxtLike, OptWithInfcx};
|
||||
use std::alloc::Layout;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
@ -119,6 +120,14 @@ impl<T: fmt::Debug> fmt::Debug for List<T> {
|
||||
(**self).fmt(f)
|
||||
}
|
||||
}
|
||||
impl<'tcx, T: super::DebugWithInfcx<TyCtxt<'tcx>>> super::DebugWithInfcx<TyCtxt<'tcx>> for List<T> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
fmt::Debug::fmt(&this.map(|this| this.as_slice()), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
|
||||
#[inline]
|
||||
@ -202,6 +211,8 @@ unsafe impl<T: Sync> Sync for List<T> {}
|
||||
// We need this since `List` uses extern type `OpaqueListContents`.
|
||||
#[cfg(parallel_compiler)]
|
||||
use rustc_data_structures::sync::DynSync;
|
||||
|
||||
use super::TyCtxt;
|
||||
#[cfg(parallel_compiler)]
|
||||
unsafe impl<T: DynSync> DynSync for List<T> {}
|
||||
|
||||
|
@ -53,6 +53,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{ExpnId, ExpnKind, Span};
|
||||
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
|
||||
pub use rustc_target::abi::{ReprFlags, ReprOptions};
|
||||
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
|
||||
pub use subst::*;
|
||||
pub use vtable::*;
|
||||
|
||||
|
@ -11,13 +11,15 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_target::abi::TyAndLayout;
|
||||
use rustc_type_ir::ConstKind;
|
||||
use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, OptWithInfcx};
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::ops::ControlFlow;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::{GenericArg, GenericArgKind, Region};
|
||||
|
||||
impl fmt::Debug for ty::TraitDef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
ty::tls::with(|tcx| {
|
||||
@ -89,7 +91,16 @@ impl fmt::Debug for ty::FreeRegion {
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = self;
|
||||
OptWithInfcx::new_no_ctx(self).fmt(f)
|
||||
}
|
||||
}
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::FnSig<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
let sig = this.data;
|
||||
let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = sig;
|
||||
|
||||
write!(f, "{}", unsafety.prefix_str())?;
|
||||
match abi {
|
||||
@ -98,15 +109,15 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
|
||||
};
|
||||
|
||||
write!(f, "fn(")?;
|
||||
let inputs = self.inputs();
|
||||
let inputs = sig.inputs();
|
||||
match inputs.len() {
|
||||
0 if *c_variadic => write!(f, "...)")?,
|
||||
0 => write!(f, ")")?,
|
||||
_ => {
|
||||
for ty in &self.inputs()[0..(self.inputs().len() - 1)] {
|
||||
write!(f, "{ty:?}, ")?;
|
||||
for ty in &sig.inputs()[0..(sig.inputs().len() - 1)] {
|
||||
write!(f, "{:?}, ", &this.wrap(ty))?;
|
||||
}
|
||||
write!(f, "{:?}", self.inputs().last().unwrap())?;
|
||||
write!(f, "{:?}", &this.wrap(sig.inputs().last().unwrap()))?;
|
||||
if *c_variadic {
|
||||
write!(f, "...")?;
|
||||
}
|
||||
@ -114,9 +125,9 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
match self.output().kind() {
|
||||
match sig.output().kind() {
|
||||
ty::Tuple(list) if list.is_empty() => Ok(()),
|
||||
_ => write!(f, " -> {:?}", self.output()),
|
||||
_ => write!(f, " -> {:?}", &this.wrap(sig.output())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,6 +144,14 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ty::DebugWithInfcx<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
this.data.fmt(f)
|
||||
}
|
||||
}
|
||||
impl<'tcx> fmt::Debug for Ty<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
with_no_trimmed_paths!(fmt::Display::fmt(self, f))
|
||||
@ -217,9 +236,17 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
|
||||
|
||||
impl<'tcx> fmt::Debug for AliasTy<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
OptWithInfcx::new_no_ctx(self).fmt(f)
|
||||
}
|
||||
}
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTy<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
f.debug_struct("AliasTy")
|
||||
.field("substs", &self.substs)
|
||||
.field("def_id", &self.def_id)
|
||||
.field("substs", &this.map(|data| data.substs))
|
||||
.field("def_id", &this.data.def_id)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
@ -232,13 +259,93 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::InferConst<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
use ty::InferConst::*;
|
||||
match this.infcx.and_then(|infcx| infcx.universe_of_ct(*this.data)) {
|
||||
None => write!(f, "{:?}", this.data),
|
||||
Some(universe) => match *this.data {
|
||||
Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()),
|
||||
Fresh(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
OptWithInfcx::new_no_ctx(self).fmt(f)
|
||||
}
|
||||
}
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
match this.data {
|
||||
ty::Expr::Binop(op, lhs, rhs) => {
|
||||
write!(f, "({op:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs))
|
||||
}
|
||||
ty::Expr::UnOp(op, rhs) => write!(f, "({op:?}: {:?})", &this.wrap(rhs)),
|
||||
ty::Expr::FunctionCall(func, args) => {
|
||||
write!(f, "{:?}(", &this.wrap(func))?;
|
||||
for arg in args.as_slice().iter().rev().skip(1).rev() {
|
||||
write!(f, "{:?}, ", &this.wrap(arg))?;
|
||||
}
|
||||
if let Some(arg) = args.last() {
|
||||
write!(f, "{:?}", &this.wrap(arg))?;
|
||||
}
|
||||
|
||||
write!(f, ")")
|
||||
}
|
||||
ty::Expr::Cast(cast_kind, lhs, rhs) => {
|
||||
write!(f, "({cast_kind:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
OptWithInfcx::new_no_ctx(self).fmt(f)
|
||||
}
|
||||
}
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
f.debug_struct("UnevaluatedConst")
|
||||
.field("def", &this.data.def)
|
||||
.field("substs", &this.wrap(this.data.substs))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::Const<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
OptWithInfcx::new_no_ctx(self).fmt(f)
|
||||
}
|
||||
}
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
// This reflects what `Const` looked liked before `Interned` was
|
||||
// introduced. We print it like this to avoid having to update expected
|
||||
// output in a lot of tests.
|
||||
write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
|
||||
write!(
|
||||
f,
|
||||
"Const {{ ty: {:?}, kind: {:?} }}",
|
||||
&this.map(|data| data.ty()),
|
||||
&this.map(|data| data.kind())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,6 +368,66 @@ impl<T: fmt::Debug> fmt::Debug for ty::Placeholder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for GenericArg<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.unpack() {
|
||||
GenericArgKind::Lifetime(lt) => lt.fmt(f),
|
||||
GenericArgKind::Type(ty) => ty.fmt(f),
|
||||
GenericArgKind::Const(ct) => ct.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for GenericArg<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
match this.data.unpack() {
|
||||
GenericArgKind::Lifetime(lt) => write!(f, "{:?}", &this.wrap(lt)),
|
||||
GenericArgKind::Const(ct) => write!(f, "{:?}", &this.wrap(ct)),
|
||||
GenericArgKind::Type(ty) => write!(f, "{:?}", &this.wrap(ty)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for Region<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self.kind())
|
||||
}
|
||||
}
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Region<'tcx> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
write!(f, "{:?}", &this.map(|data| data.kind()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::RegionVid {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
match this.infcx.and_then(|infcx| infcx.universe_of_lt(*this.data)) {
|
||||
Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
|
||||
None => write!(f, "{:?}", this.data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
|
||||
fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
f.debug_tuple("Binder")
|
||||
.field(&this.map(|data| data.as_ref().skip_binder()))
|
||||
.field(&this.data.bound_vars())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Atomic structs
|
||||
//
|
||||
|
@ -35,9 +35,12 @@ use std::ops::{ControlFlow, Deref, Range};
|
||||
use ty::util::IntTypeExt;
|
||||
|
||||
use rustc_type_ir::sty::TyKind::*;
|
||||
use rustc_type_ir::CollectAndApply;
|
||||
use rustc_type_ir::ConstKind as IrConstKind;
|
||||
use rustc_type_ir::DebugWithInfcx;
|
||||
use rustc_type_ir::DynKind;
|
||||
use rustc_type_ir::RegionKind as IrRegionKind;
|
||||
use rustc_type_ir::TyKind as IrTyKind;
|
||||
use rustc_type_ir::{CollectAndApply, ConstKind as IrConstKind};
|
||||
use rustc_type_ir::{DynKind, RegionKind as IrRegionKind};
|
||||
|
||||
use super::GenericParamDefKind;
|
||||
|
||||
@ -694,6 +697,15 @@ pub enum ExistentialPredicate<'tcx> {
|
||||
AutoTrait(DefId),
|
||||
}
|
||||
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ExistentialPredicate<'tcx> {
|
||||
fn fmt<InfCtx: rustc_type_ir::InferCtxtLike<TyCtxt<'tcx>>>(
|
||||
this: rustc_type_ir::OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
fmt::Debug::fmt(&this.data, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ExistentialPredicate<'tcx> {
|
||||
/// Compares via an ordering that will not change if modules are reordered or other changes are
|
||||
/// made to the tree. In particular, this ordering is preserved across incremental compilations.
|
||||
@ -1571,12 +1583,6 @@ impl<'tcx> Deref for Region<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for Region<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self.kind())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
|
||||
#[derive(HashStable)]
|
||||
pub struct EarlyBoundRegion {
|
||||
|
@ -17,7 +17,6 @@ use smallvec::SmallVec;
|
||||
|
||||
use core::intrinsics;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::num::NonZeroUsize;
|
||||
@ -80,16 +79,6 @@ impl<'tcx> GenericArgKind<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for GenericArg<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.unpack() {
|
||||
GenericArgKind::Lifetime(lt) => lt.fmt(f),
|
||||
GenericArgKind::Type(ty) => ty.fmt(f),
|
||||
GenericArgKind::Const(ct) => ct.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Ord for GenericArg<'tcx> {
|
||||
fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering {
|
||||
self.unpack().cmp(&other.unpack())
|
||||
|
@ -31,6 +31,7 @@ mod macros;
|
||||
mod structural_impls;
|
||||
|
||||
pub use codec::*;
|
||||
pub use structural_impls::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
|
||||
pub use sty::*;
|
||||
pub use ty_info::*;
|
||||
|
||||
@ -39,41 +40,41 @@ pub trait HashStableContext {}
|
||||
|
||||
pub trait Interner: Sized {
|
||||
type AdtDef: Clone + Debug + Hash + Ord;
|
||||
type SubstsRef: Clone + Debug + Hash + Ord;
|
||||
type SubstsRef: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type DefId: Clone + Debug + Hash + Ord;
|
||||
type Binder<T>;
|
||||
type Ty: Clone + Debug + Hash + Ord;
|
||||
type Const: Clone + Debug + Hash + Ord;
|
||||
type Region: Clone + Debug + Hash + Ord;
|
||||
type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type Predicate;
|
||||
type TypeAndMut: Clone + Debug + Hash + Ord;
|
||||
type Mutability: Clone + Debug + Hash + Ord;
|
||||
type Movability: Clone + Debug + Hash + Ord;
|
||||
type PolyFnSig: Clone + Debug + Hash + Ord;
|
||||
type ListBinderExistentialPredicate: Clone + Debug + Hash + Ord;
|
||||
type BinderListTy: Clone + Debug + Hash + Ord;
|
||||
type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type ListBinderExistentialPredicate: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type BinderListTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type ListTy: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
|
||||
type AliasTy: Clone + Debug + Hash + Ord;
|
||||
type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type ParamTy: Clone + Debug + Hash + Ord;
|
||||
type BoundTy: Clone + Debug + Hash + Ord;
|
||||
type PlaceholderType: Clone + Debug + Hash + Ord;
|
||||
type InferTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type ErrorGuaranteed: Clone + Debug + Hash + Ord;
|
||||
type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
|
||||
type AllocId: Clone + Debug + Hash + Ord;
|
||||
|
||||
type InferConst: Clone + Debug + Hash + Ord;
|
||||
type AliasConst: Clone + Debug + Hash + Ord;
|
||||
type InferConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PlaceholderConst: Clone + Debug + Hash + Ord;
|
||||
type ParamConst: Clone + Debug + Hash + Ord;
|
||||
type BoundConst: Clone + Debug + Hash + Ord;
|
||||
type InferTy: Clone + Debug + Hash + Ord;
|
||||
type ValueConst: Clone + Debug + Hash + Ord;
|
||||
type ExprConst: Clone + Debug + Hash + Ord;
|
||||
type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
|
||||
type EarlyBoundRegion: Clone + Debug + Hash + Ord;
|
||||
type BoundRegion: Clone + Debug + Hash + Ord;
|
||||
type FreeRegion: Clone + Debug + Hash + Ord;
|
||||
type RegionVid: Clone + Debug + Hash + Ord;
|
||||
type RegionVid: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PlaceholderRegion: Clone + Debug + Hash + Ord;
|
||||
|
||||
fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability);
|
||||
@ -775,20 +776,6 @@ impl fmt::Debug for FloatVid {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for InferTy {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use InferTy::*;
|
||||
match *self {
|
||||
TyVar(ref v) => v.fmt(f),
|
||||
IntVar(ref v) => v.fmt(f),
|
||||
FloatVar(ref v) => v.fmt(f),
|
||||
FreshTy(v) => write!(f, "FreshTy({v:?})"),
|
||||
FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
|
||||
FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Variance {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match *self {
|
||||
|
@ -4,12 +4,13 @@
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::{ConstKind, FloatTy, IntTy, Interner, UintTy};
|
||||
use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex};
|
||||
use rustc_data_structures::functor::IdFunctor;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
|
||||
use core::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -165,6 +166,116 @@ impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Debug impls
|
||||
|
||||
pub trait InferCtxtLike<I: Interner> {
|
||||
fn universe_of_ty(&self, ty: I::InferTy) -> Option<UniverseIndex>;
|
||||
fn universe_of_lt(&self, lt: I::RegionVid) -> Option<UniverseIndex>;
|
||||
fn universe_of_ct(&self, ct: I::InferConst) -> Option<UniverseIndex>;
|
||||
}
|
||||
|
||||
impl<I: Interner> InferCtxtLike<I> for core::convert::Infallible {
|
||||
fn universe_of_ty(&self, _ty: <I as Interner>::InferTy) -> Option<UniverseIndex> {
|
||||
match *self {}
|
||||
}
|
||||
fn universe_of_ct(&self, _ct: <I as Interner>::InferConst) -> Option<UniverseIndex> {
|
||||
match *self {}
|
||||
}
|
||||
fn universe_of_lt(&self, _lt: <I as Interner>::RegionVid) -> Option<UniverseIndex> {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
|
||||
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result;
|
||||
}
|
||||
|
||||
impl<I: Interner, T: DebugWithInfcx<I> + ?Sized> DebugWithInfcx<I> for &'_ T {
|
||||
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
<T as DebugWithInfcx<I>>::fmt(this.map(|&data| data), f)
|
||||
}
|
||||
}
|
||||
impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for [T] {
|
||||
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
match f.alternate() {
|
||||
true => {
|
||||
write!(f, "[\n")?;
|
||||
for element in this.data.iter() {
|
||||
write!(f, "{:?},\n", &this.wrap(element))?;
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
false => {
|
||||
write!(f, "[")?;
|
||||
if this.data.len() > 0 {
|
||||
for element in &this.data[..(this.data.len() - 1)] {
|
||||
write!(f, "{:?}, ", &this.wrap(element))?;
|
||||
}
|
||||
if let Some(element) = this.data.last() {
|
||||
write!(f, "{:?}", &this.wrap(element))?;
|
||||
}
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OptWithInfcx<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> {
|
||||
pub data: T,
|
||||
pub infcx: Option<&'a InfCtx>,
|
||||
_interner: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Copy> Copy for OptWithInfcx<'_, I, InfCtx, T> {}
|
||||
impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Clone> Clone for OptWithInfcx<'_, I, InfCtx, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> {
|
||||
pub fn new_no_ctx(data: T) -> Self {
|
||||
Self { data, infcx: None, _interner: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> OptWithInfcx<'a, I, InfCtx, T> {
|
||||
pub fn new(data: T, infcx: &'a InfCtx) -> Self {
|
||||
Self { data, infcx: Some(infcx), _interner: PhantomData }
|
||||
}
|
||||
|
||||
pub fn wrap<U>(self, u: U) -> OptWithInfcx<'a, I, InfCtx, U> {
|
||||
OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData }
|
||||
}
|
||||
|
||||
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, InfCtx, U> {
|
||||
OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData }
|
||||
}
|
||||
|
||||
pub fn as_ref(&self) -> OptWithInfcx<'a, I, InfCtx, &T> {
|
||||
OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, InfCtx: InferCtxtLike<I>, T: DebugWithInfcx<I>> fmt::Debug
|
||||
for OptWithInfcx<'_, I, InfCtx, T>
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
DebugWithInfcx::fmt(self.as_ref(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for IntTy {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.name_str())
|
||||
@ -183,20 +294,60 @@ impl fmt::Debug for FloatTy {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ConstKind<I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
use ConstKind::*;
|
||||
match self {
|
||||
Param(param) => write!(f, "{param:?}"),
|
||||
Infer(var) => write!(f, "{var:?}"),
|
||||
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
|
||||
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
|
||||
Unevaluated(uv) => {
|
||||
write!(f, "{uv:?}")
|
||||
}
|
||||
Value(valtree) => write!(f, "{valtree:?}"),
|
||||
Error(_) => write!(f, "{{const error}}"),
|
||||
Expr(expr) => write!(f, "{expr:?}"),
|
||||
impl fmt::Debug for InferTy {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use InferTy::*;
|
||||
match *self {
|
||||
TyVar(ref v) => v.fmt(f),
|
||||
IntVar(ref v) => v.fmt(f),
|
||||
FloatVar(ref v) => v.fmt(f),
|
||||
FreshTy(v) => write!(f, "FreshTy({v:?})"),
|
||||
FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
|
||||
FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<I: Interner<InferTy = InferTy>> DebugWithInfcx<I> for InferTy {
|
||||
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
use InferTy::*;
|
||||
match this.infcx.and_then(|infcx| infcx.universe_of_ty(*this.data)) {
|
||||
None => write!(f, "{:?}", this.data),
|
||||
Some(universe) => match *this.data {
|
||||
TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()),
|
||||
IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ConstKind<I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
OptWithInfcx::new_no_ctx(self).fmt(f)
|
||||
}
|
||||
}
|
||||
impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
|
||||
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
use ConstKind::*;
|
||||
|
||||
match this.data {
|
||||
Param(param) => write!(f, "{param:?}"),
|
||||
Infer(var) => write!(f, "{:?}", &this.wrap(var)),
|
||||
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
|
||||
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
|
||||
Unevaluated(uv) => {
|
||||
write!(f, "{:?}", &this.wrap(uv))
|
||||
}
|
||||
Value(valtree) => write!(f, "{valtree:?}"),
|
||||
Error(_) => write!(f, "{{const error}}"),
|
||||
Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::{fmt, hash};
|
||||
|
||||
use crate::DebruijnIndex;
|
||||
use crate::FloatTy;
|
||||
use crate::HashStableContext;
|
||||
use crate::IntTy;
|
||||
@ -11,6 +10,7 @@ use crate::Interner;
|
||||
use crate::TyDecoder;
|
||||
use crate::TyEncoder;
|
||||
use crate::UintTy;
|
||||
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx};
|
||||
|
||||
use self::RegionKind::*;
|
||||
use self::TyKind::*;
|
||||
@ -503,42 +503,48 @@ impl<I: Interner> hash::Hash for TyKind<I> {
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Debug`
|
||||
impl<I: Interner> fmt::Debug for TyKind<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
|
||||
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
match this.data {
|
||||
Bool => write!(f, "bool"),
|
||||
Char => write!(f, "char"),
|
||||
Int(i) => write!(f, "{i:?}"),
|
||||
Uint(u) => write!(f, "{u:?}"),
|
||||
Float(float) => write!(f, "{float:?}"),
|
||||
Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s),
|
||||
Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, &this.wrap(s)),
|
||||
Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
|
||||
Str => write!(f, "str"),
|
||||
Array(t, c) => write!(f, "[{t:?}; {c:?}]"),
|
||||
Slice(t) => write!(f, "[{t:?}]"),
|
||||
Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
|
||||
Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
|
||||
RawPtr(p) => {
|
||||
let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
|
||||
match I::mutability_is_mut(mutbl) {
|
||||
true => write!(f, "*mut "),
|
||||
false => write!(f, "*const "),
|
||||
}?;
|
||||
write!(f, "{ty:?}")
|
||||
write!(f, "{:?}", &this.wrap(ty))
|
||||
}
|
||||
Ref(r, t, m) => match I::mutability_is_mut(m.clone()) {
|
||||
true => write!(f, "&{r:?} mut {t:?}"),
|
||||
false => write!(f, "&{r:?} {t:?}"),
|
||||
true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
|
||||
false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)),
|
||||
},
|
||||
FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s),
|
||||
FnPtr(s) => write!(f, "{s:?}"),
|
||||
FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)),
|
||||
FnPtr(s) => write!(f, "{:?}", &this.wrap(s)),
|
||||
Dynamic(p, r, repr) => match repr {
|
||||
DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
|
||||
DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
|
||||
DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)),
|
||||
DynKind::DynStar => {
|
||||
write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r))
|
||||
}
|
||||
},
|
||||
Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s),
|
||||
Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m),
|
||||
GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
|
||||
GeneratorWitnessMIR(d, s) => f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, s),
|
||||
Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)),
|
||||
Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, &this.wrap(s), m),
|
||||
GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", &this.wrap(g)),
|
||||
GeneratorWitnessMIR(d, s) => {
|
||||
f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, &this.wrap(s))
|
||||
}
|
||||
Never => write!(f, "!"),
|
||||
Tuple(t) => {
|
||||
let mut iter = t.clone().into_iter();
|
||||
@ -547,28 +553,34 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
|
||||
|
||||
match iter.next() {
|
||||
None => return write!(f, ")"),
|
||||
Some(ty) => write!(f, "{ty:?}")?,
|
||||
Some(ty) => write!(f, "{:?}", &this.wrap(ty))?,
|
||||
};
|
||||
|
||||
match iter.next() {
|
||||
None => return write!(f, ",)"),
|
||||
Some(ty) => write!(f, "{ty:?})")?,
|
||||
Some(ty) => write!(f, "{:?})", &this.wrap(ty))?,
|
||||
}
|
||||
|
||||
for ty in iter {
|
||||
write!(f, ", {ty:?}")?;
|
||||
write!(f, ", {:?}", &this.wrap(ty))?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
|
||||
Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, &this.wrap(a)),
|
||||
Param(p) => write!(f, "{p:?}"),
|
||||
Bound(d, b) => crate::debug_bound_var(f, *d, b),
|
||||
Placeholder(p) => write!(f, "{p:?}"),
|
||||
Infer(t) => write!(f, "{t:?}"),
|
||||
Infer(t) => write!(f, "{:?}", this.wrap(t)),
|
||||
TyKind::Error(_) => write!(f, "{{type error}}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is manually implemented because a derive would require `I: Debug`
|
||||
impl<I: Interner> fmt::Debug for TyKind<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
OptWithInfcx::new_no_ctx(self).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Encodable`
|
||||
impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
|
||||
@ -1356,21 +1368,23 @@ impl<I: Interner> hash::Hash for RegionKind<I> {
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Debug`
|
||||
impl<I: Interner> fmt::Debug for RegionKind<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
|
||||
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||
f: &mut core::fmt::Formatter<'_>,
|
||||
) -> core::fmt::Result {
|
||||
match this.data {
|
||||
ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
|
||||
|
||||
ReLateBound(binder_id, bound_region) => {
|
||||
write!(f, "ReLateBound({binder_id:?}, {bound_region:?})")
|
||||
}
|
||||
|
||||
ReFree(fr) => fr.fmt(f),
|
||||
ReFree(fr) => write!(f, "{fr:?}"),
|
||||
|
||||
ReStatic => f.write_str("ReStatic"),
|
||||
|
||||
ReVar(vid) => vid.fmt(f),
|
||||
ReVar(vid) => write!(f, "{:?}", &this.wrap(vid)),
|
||||
|
||||
RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"),
|
||||
|
||||
@ -1380,6 +1394,11 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<I: Interner> fmt::Debug for RegionKind<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
OptWithInfcx::new_no_ctx(self).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Encodable`
|
||||
impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
|
||||
|
Loading…
Reference in New Issue
Block a user