Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce trait DebugWithInfcx to debug format types with universe info #112984

Merged
merged 1 commit into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow yeah that's jank. The way regions does it is so much better.

// 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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lmao if only we stored the universe not in the eq relation table for ty/ct

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably perf-negative but I'd like to see it tested, perhaps as a follow-up by someone who's interested in contributing.

}
}

/// See the `error_reporting` module for more details.
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
pub enum ValuePairs<'tcx> {
Expand Down Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/consts/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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>),
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_middle/src/ty/list.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ideally, if we found some new contributor, it would be cool if we could derive(DebugWithInfcx) or sth. Manual impls are not the worst thing in the world, though..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I would love to see a derive(DebugWithInfcx)

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]
Expand Down Expand Up @@ -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> {}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;

Expand Down
191 changes: 179 additions & 12 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down Expand Up @@ -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 {
Expand All @@ -98,25 +109,25 @@ 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, "...")?;
}
write!(f, ")")?;
}
}

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())),
}
}
}
Expand All @@ -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))
Expand Down Expand Up @@ -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()
}
}
Expand All @@ -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())
)
}
}

Expand All @@ -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
//
Expand Down
Loading