mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-07 20:43:03 +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,
|
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.
|
/// See the `error_reporting` module for more details.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
|
||||||
pub enum ValuePairs<'tcx> {
|
pub enum ValuePairs<'tcx> {
|
||||||
@ -1068,6 +1101,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
self.inner.borrow_mut().unwrap_region_constraints().universe(r)
|
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.
|
/// Number of region variables created so far.
|
||||||
pub fn num_region_vars(&self) -> usize {
|
pub fn num_region_vars(&self) -> usize {
|
||||||
self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
|
self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
|
||||||
|
@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId;
|
|||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
|
|
||||||
/// An unevaluated (potentially generic) constant used in the type-system.
|
/// 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)]
|
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
pub struct UnevaluatedConst<'tcx> {
|
pub struct UnevaluatedConst<'tcx> {
|
||||||
pub def: DefId,
|
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)]
|
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
||||||
pub enum Expr<'tcx> {
|
pub enum Expr<'tcx> {
|
||||||
Binop(mir::BinOp, Const<'tcx>, Const<'tcx>),
|
Binop(mir::BinOp, Const<'tcx>, Const<'tcx>),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::arena::Arena;
|
use crate::arena::Arena;
|
||||||
use rustc_data_structures::aligned::{align_of, Aligned};
|
use rustc_data_structures::aligned::{align_of, Aligned};
|
||||||
use rustc_serialize::{Encodable, Encoder};
|
use rustc_serialize::{Encodable, Encoder};
|
||||||
|
use rustc_type_ir::{InferCtxtLike, OptWithInfcx};
|
||||||
use std::alloc::Layout;
|
use std::alloc::Layout;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -119,6 +120,14 @@ impl<T: fmt::Debug> fmt::Debug for List<T> {
|
|||||||
(**self).fmt(f)
|
(**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> {
|
impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -202,6 +211,8 @@ unsafe impl<T: Sync> Sync for List<T> {}
|
|||||||
// We need this since `List` uses extern type `OpaqueListContents`.
|
// We need this since `List` uses extern type `OpaqueListContents`.
|
||||||
#[cfg(parallel_compiler)]
|
#[cfg(parallel_compiler)]
|
||||||
use rustc_data_structures::sync::DynSync;
|
use rustc_data_structures::sync::DynSync;
|
||||||
|
|
||||||
|
use super::TyCtxt;
|
||||||
#[cfg(parallel_compiler)]
|
#[cfg(parallel_compiler)]
|
||||||
unsafe impl<T: DynSync> DynSync for List<T> {}
|
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_span::{ExpnId, ExpnKind, Span};
|
||||||
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
|
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
|
||||||
pub use rustc_target::abi::{ReprFlags, ReprOptions};
|
pub use rustc_target::abi::{ReprFlags, ReprOptions};
|
||||||
|
pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
|
||||||
pub use subst::*;
|
pub use subst::*;
|
||||||
pub use vtable::*;
|
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_hir::def::Namespace;
|
||||||
use rustc_index::{Idx, IndexVec};
|
use rustc_index::{Idx, IndexVec};
|
||||||
use rustc_target::abi::TyAndLayout;
|
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::ops::ControlFlow;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use super::{GenericArg, GenericArgKind, Region};
|
||||||
|
|
||||||
impl fmt::Debug for ty::TraitDef {
|
impl fmt::Debug for ty::TraitDef {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
ty::tls::with(|tcx| {
|
ty::tls::with(|tcx| {
|
||||||
@ -89,7 +91,16 @@ impl fmt::Debug for ty::FreeRegion {
|
|||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
|
impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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())?;
|
write!(f, "{}", unsafety.prefix_str())?;
|
||||||
match abi {
|
match abi {
|
||||||
@ -98,15 +109,15 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
write!(f, "fn(")?;
|
write!(f, "fn(")?;
|
||||||
let inputs = self.inputs();
|
let inputs = sig.inputs();
|
||||||
match inputs.len() {
|
match inputs.len() {
|
||||||
0 if *c_variadic => write!(f, "...)")?,
|
0 if *c_variadic => write!(f, "...)")?,
|
||||||
0 => write!(f, ")")?,
|
0 => write!(f, ")")?,
|
||||||
_ => {
|
_ => {
|
||||||
for ty in &self.inputs()[0..(self.inputs().len() - 1)] {
|
for ty in &sig.inputs()[0..(sig.inputs().len() - 1)] {
|
||||||
write!(f, "{ty:?}, ")?;
|
write!(f, "{:?}, ", &this.wrap(ty))?;
|
||||||
}
|
}
|
||||||
write!(f, "{:?}", self.inputs().last().unwrap())?;
|
write!(f, "{:?}", &this.wrap(sig.inputs().last().unwrap()))?;
|
||||||
if *c_variadic {
|
if *c_variadic {
|
||||||
write!(f, "...")?;
|
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(()),
|
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> {
|
impl<'tcx> fmt::Debug for Ty<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
with_no_trimmed_paths!(fmt::Display::fmt(self, f))
|
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> {
|
impl<'tcx> fmt::Debug for AliasTy<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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")
|
f.debug_struct("AliasTy")
|
||||||
.field("substs", &self.substs)
|
.field("substs", &this.map(|data| data.substs))
|
||||||
.field("def_id", &self.def_id)
|
.field("def_id", &this.data.def_id)
|
||||||
.finish()
|
.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> {
|
impl<'tcx> fmt::Debug for ty::Const<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
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
|
// This reflects what `Const` looked liked before `Interned` was
|
||||||
// introduced. We print it like this to avoid having to update expected
|
// introduced. We print it like this to avoid having to update expected
|
||||||
// output in a lot of tests.
|
// 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
|
// Atomic structs
|
||||||
//
|
//
|
||||||
|
@ -35,9 +35,12 @@ use std::ops::{ControlFlow, Deref, Range};
|
|||||||
use ty::util::IntTypeExt;
|
use ty::util::IntTypeExt;
|
||||||
|
|
||||||
use rustc_type_ir::sty::TyKind::*;
|
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::TyKind as IrTyKind;
|
||||||
use rustc_type_ir::{CollectAndApply, ConstKind as IrConstKind};
|
|
||||||
use rustc_type_ir::{DynKind, RegionKind as IrRegionKind};
|
|
||||||
|
|
||||||
use super::GenericParamDefKind;
|
use super::GenericParamDefKind;
|
||||||
|
|
||||||
@ -694,6 +697,15 @@ pub enum ExistentialPredicate<'tcx> {
|
|||||||
AutoTrait(DefId),
|
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> {
|
impl<'tcx> ExistentialPredicate<'tcx> {
|
||||||
/// Compares via an ordering that will not change if modules are reordered or other changes are
|
/// 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.
|
/// 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(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
|
||||||
#[derive(HashStable)]
|
#[derive(HashStable)]
|
||||||
pub struct EarlyBoundRegion {
|
pub struct EarlyBoundRegion {
|
||||||
|
@ -17,7 +17,6 @@ use smallvec::SmallVec;
|
|||||||
|
|
||||||
use core::intrinsics;
|
use core::intrinsics;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::num::NonZeroUsize;
|
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> {
|
impl<'tcx> Ord for GenericArg<'tcx> {
|
||||||
fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering {
|
fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering {
|
||||||
self.unpack().cmp(&other.unpack())
|
self.unpack().cmp(&other.unpack())
|
||||||
|
@ -31,6 +31,7 @@ mod macros;
|
|||||||
mod structural_impls;
|
mod structural_impls;
|
||||||
|
|
||||||
pub use codec::*;
|
pub use codec::*;
|
||||||
|
pub use structural_impls::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
|
||||||
pub use sty::*;
|
pub use sty::*;
|
||||||
pub use ty_info::*;
|
pub use ty_info::*;
|
||||||
|
|
||||||
@ -39,41 +40,41 @@ pub trait HashStableContext {}
|
|||||||
|
|
||||||
pub trait Interner: Sized {
|
pub trait Interner: Sized {
|
||||||
type AdtDef: Clone + Debug + Hash + Ord;
|
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 DefId: Clone + Debug + Hash + Ord;
|
||||||
type Binder<T>;
|
type Binder<T>;
|
||||||
type Ty: Clone + Debug + Hash + Ord;
|
type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type Const: Clone + Debug + Hash + Ord;
|
type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type Region: Clone + Debug + Hash + Ord;
|
type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type Predicate;
|
type Predicate;
|
||||||
type TypeAndMut: Clone + Debug + Hash + Ord;
|
type TypeAndMut: Clone + Debug + Hash + Ord;
|
||||||
type Mutability: Clone + Debug + Hash + Ord;
|
type Mutability: Clone + Debug + Hash + Ord;
|
||||||
type Movability: Clone + Debug + Hash + Ord;
|
type Movability: Clone + Debug + Hash + Ord;
|
||||||
type PolyFnSig: Clone + Debug + Hash + Ord;
|
type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type ListBinderExistentialPredicate: Clone + Debug + Hash + Ord;
|
type ListBinderExistentialPredicate: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type BinderListTy: Clone + Debug + Hash + Ord;
|
type BinderListTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type ListTy: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
|
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 ParamTy: Clone + Debug + Hash + Ord;
|
||||||
type BoundTy: Clone + Debug + Hash + Ord;
|
type BoundTy: Clone + Debug + Hash + Ord;
|
||||||
type PlaceholderType: Clone + Debug + Hash + Ord;
|
type PlaceholderType: Clone + Debug + Hash + Ord;
|
||||||
|
type InferTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type ErrorGuaranteed: Clone + Debug + Hash + Ord;
|
type ErrorGuaranteed: Clone + Debug + Hash + Ord;
|
||||||
type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
|
type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
|
||||||
type AllocId: Clone + Debug + Hash + Ord;
|
type AllocId: Clone + Debug + Hash + Ord;
|
||||||
|
|
||||||
type InferConst: Clone + Debug + Hash + Ord;
|
type InferConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type AliasConst: Clone + Debug + Hash + Ord;
|
type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type PlaceholderConst: Clone + Debug + Hash + Ord;
|
type PlaceholderConst: Clone + Debug + Hash + Ord;
|
||||||
type ParamConst: Clone + Debug + Hash + Ord;
|
type ParamConst: Clone + Debug + Hash + Ord;
|
||||||
type BoundConst: Clone + Debug + Hash + Ord;
|
type BoundConst: Clone + Debug + Hash + Ord;
|
||||||
type InferTy: Clone + Debug + Hash + Ord;
|
|
||||||
type ValueConst: 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 EarlyBoundRegion: Clone + Debug + Hash + Ord;
|
||||||
type BoundRegion: Clone + Debug + Hash + Ord;
|
type BoundRegion: Clone + Debug + Hash + Ord;
|
||||||
type FreeRegion: 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;
|
type PlaceholderRegion: Clone + Debug + Hash + Ord;
|
||||||
|
|
||||||
fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability);
|
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 {
|
impl fmt::Debug for Variance {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.write_str(match *self {
|
f.write_str(match *self {
|
||||||
|
@ -4,12 +4,13 @@
|
|||||||
|
|
||||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
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::functor::IdFunctor;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_index::{Idx, IndexVec};
|
use rustc_index::{Idx, IndexVec};
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::ops::ControlFlow;
|
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 {
|
impl fmt::Debug for IntTy {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.name_str())
|
write!(f, "{}", self.name_str())
|
||||||
@ -183,20 +294,60 @@ impl fmt::Debug for FloatTy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Interner> fmt::Debug for ConstKind<I> {
|
impl fmt::Debug for InferTy {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
use ConstKind::*;
|
use InferTy::*;
|
||||||
match self {
|
match *self {
|
||||||
Param(param) => write!(f, "{param:?}"),
|
TyVar(ref v) => v.fmt(f),
|
||||||
Infer(var) => write!(f, "{var:?}"),
|
IntVar(ref v) => v.fmt(f),
|
||||||
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
|
FloatVar(ref v) => v.fmt(f),
|
||||||
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
|
FreshTy(v) => write!(f, "FreshTy({v:?})"),
|
||||||
Unevaluated(uv) => {
|
FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
|
||||||
write!(f, "{uv:?}")
|
FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
|
||||||
}
|
}
|
||||||
Value(valtree) => write!(f, "{valtree:?}"),
|
}
|
||||||
Error(_) => write!(f, "{{const error}}"),
|
}
|
||||||
Expr(expr) => write!(f, "{expr:?}"),
|
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::cmp::Ordering;
|
||||||
use std::{fmt, hash};
|
use std::{fmt, hash};
|
||||||
|
|
||||||
use crate::DebruijnIndex;
|
|
||||||
use crate::FloatTy;
|
use crate::FloatTy;
|
||||||
use crate::HashStableContext;
|
use crate::HashStableContext;
|
||||||
use crate::IntTy;
|
use crate::IntTy;
|
||||||
@ -11,6 +10,7 @@ use crate::Interner;
|
|||||||
use crate::TyDecoder;
|
use crate::TyDecoder;
|
||||||
use crate::TyEncoder;
|
use crate::TyEncoder;
|
||||||
use crate::UintTy;
|
use crate::UintTy;
|
||||||
|
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx};
|
||||||
|
|
||||||
use self::RegionKind::*;
|
use self::RegionKind::*;
|
||||||
use self::TyKind::*;
|
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> DebugWithInfcx<I> for TyKind<I> {
|
||||||
impl<I: Interner> fmt::Debug for TyKind<I> {
|
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||||
match self {
|
f: &mut core::fmt::Formatter<'_>,
|
||||||
|
) -> fmt::Result {
|
||||||
|
match this.data {
|
||||||
Bool => write!(f, "bool"),
|
Bool => write!(f, "bool"),
|
||||||
Char => write!(f, "char"),
|
Char => write!(f, "char"),
|
||||||
Int(i) => write!(f, "{i:?}"),
|
Int(i) => write!(f, "{i:?}"),
|
||||||
Uint(u) => write!(f, "{u:?}"),
|
Uint(u) => write!(f, "{u:?}"),
|
||||||
Float(float) => write!(f, "{float:?}"),
|
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),
|
Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
|
||||||
Str => write!(f, "str"),
|
Str => write!(f, "str"),
|
||||||
Array(t, c) => write!(f, "[{t:?}; {c:?}]"),
|
Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
|
||||||
Slice(t) => write!(f, "[{t:?}]"),
|
Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
|
||||||
RawPtr(p) => {
|
RawPtr(p) => {
|
||||||
let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
|
let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
|
||||||
match I::mutability_is_mut(mutbl) {
|
match I::mutability_is_mut(mutbl) {
|
||||||
true => write!(f, "*mut "),
|
true => write!(f, "*mut "),
|
||||||
false => write!(f, "*const "),
|
false => write!(f, "*const "),
|
||||||
}?;
|
}?;
|
||||||
write!(f, "{ty:?}")
|
write!(f, "{:?}", &this.wrap(ty))
|
||||||
}
|
}
|
||||||
Ref(r, t, m) => match I::mutability_is_mut(m.clone()) {
|
Ref(r, t, m) => match I::mutability_is_mut(m.clone()) {
|
||||||
true => write!(f, "&{r:?} mut {t:?}"),
|
true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
|
||||||
false => write!(f, "&{r:?} {t:?}"),
|
false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)),
|
||||||
},
|
},
|
||||||
FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s),
|
FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)),
|
||||||
FnPtr(s) => write!(f, "{s:?}"),
|
FnPtr(s) => write!(f, "{:?}", &this.wrap(s)),
|
||||||
Dynamic(p, r, repr) => match repr {
|
Dynamic(p, r, repr) => match repr {
|
||||||
DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
|
DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)),
|
||||||
DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
|
DynKind::DynStar => {
|
||||||
|
write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Closure(d, s) => f.debug_tuple_field2_finish("Closure", 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, s, m),
|
Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, &this.wrap(s), m),
|
||||||
GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
|
GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", &this.wrap(g)),
|
||||||
GeneratorWitnessMIR(d, s) => f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, s),
|
GeneratorWitnessMIR(d, s) => {
|
||||||
|
f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, &this.wrap(s))
|
||||||
|
}
|
||||||
Never => write!(f, "!"),
|
Never => write!(f, "!"),
|
||||||
Tuple(t) => {
|
Tuple(t) => {
|
||||||
let mut iter = t.clone().into_iter();
|
let mut iter = t.clone().into_iter();
|
||||||
@ -547,28 +553,34 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
|
|||||||
|
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
None => return write!(f, ")"),
|
None => return write!(f, ")"),
|
||||||
Some(ty) => write!(f, "{ty:?}")?,
|
Some(ty) => write!(f, "{:?}", &this.wrap(ty))?,
|
||||||
};
|
};
|
||||||
|
|
||||||
match iter.next() {
|
match iter.next() {
|
||||||
None => return write!(f, ",)"),
|
None => return write!(f, ",)"),
|
||||||
Some(ty) => write!(f, "{ty:?})")?,
|
Some(ty) => write!(f, "{:?})", &this.wrap(ty))?,
|
||||||
}
|
}
|
||||||
|
|
||||||
for ty in iter {
|
for ty in iter {
|
||||||
write!(f, ", {ty:?}")?;
|
write!(f, ", {:?}", &this.wrap(ty))?;
|
||||||
}
|
}
|
||||||
write!(f, ")")
|
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:?}"),
|
Param(p) => write!(f, "{p:?}"),
|
||||||
Bound(d, b) => crate::debug_bound_var(f, *d, b),
|
Bound(d, b) => crate::debug_bound_var(f, *d, b),
|
||||||
Placeholder(p) => write!(f, "{p:?}"),
|
Placeholder(p) => write!(f, "{p:?}"),
|
||||||
Infer(t) => write!(f, "{t:?}"),
|
Infer(t) => write!(f, "{:?}", this.wrap(t)),
|
||||||
TyKind::Error(_) => write!(f, "{{type error}}"),
|
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`
|
// This is manually implemented because a derive would require `I: Encodable`
|
||||||
impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
|
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> DebugWithInfcx<I> for RegionKind<I> {
|
||||||
impl<I: Interner> fmt::Debug for RegionKind<I> {
|
fn fmt<InfCtx: InferCtxtLike<I>>(
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
this: OptWithInfcx<'_, I, InfCtx, &Self>,
|
||||||
match self {
|
f: &mut core::fmt::Formatter<'_>,
|
||||||
|
) -> core::fmt::Result {
|
||||||
|
match this.data {
|
||||||
ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
|
ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
|
||||||
|
|
||||||
ReLateBound(binder_id, bound_region) => {
|
ReLateBound(binder_id, bound_region) => {
|
||||||
write!(f, "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"),
|
ReStatic => f.write_str("ReStatic"),
|
||||||
|
|
||||||
ReVar(vid) => vid.fmt(f),
|
ReVar(vid) => write!(f, "{:?}", &this.wrap(vid)),
|
||||||
|
|
||||||
RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"),
|
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`
|
// This is manually implemented because a derive would require `I: Encodable`
|
||||||
impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
|
impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
|
||||||
|
Loading…
Reference in New Issue
Block a user