Skip to content

Allow printing TraitRef and TraitPredicate with Infcx information #125262

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

Closed
wants to merge 4 commits into from
Closed
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
15 changes: 14 additions & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ use crate::traits::solve::{
ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
};
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
@@ -52,7 +53,7 @@ use rustc_errors::{
Applicability, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, LintDiagnostic, MultiSpan,
};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def::{DefKind, Namespace};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
use rustc_hir::intravisit::Visitor;
@@ -89,6 +90,18 @@ use std::ops::{Bound, Deref};
#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Interner for TyCtxt<'tcx> {
type DefId = DefId;
fn print_def_path(defid: Self::DefId, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
ty::tls::with(|tcx| {
with_no_trimmed_paths!({
// this namespace is..... not strictly correct lol
let s = FmtPrinter::print_string(tcx, Namespace::TypeNS, |cx| {
cx.print_def_path(defid, &[])
})?;
f.write_str(&s)
})
})
}

type AdtDef = ty::AdtDef<'tcx>;

type GenericArgs = ty::GenericArgsRef<'tcx>;
19 changes: 11 additions & 8 deletions compiler/rustc_middle/src/ty/structural_impls.rs
Original file line number Diff line number Diff line change
@@ -83,17 +83,17 @@ impl fmt::Debug for ty::LateParamRegion {
}
}

impl<'tcx> fmt::Debug for Ty<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
with_no_trimmed_paths!(self.kind().fmt(f))
}
}
impl<'tcx> ty::DebugWithInfcx<TyCtxt<'tcx>> for Ty<'tcx> {
fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>(
this: WithInfcx<'_, Infcx, &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::Debug::fmt(self.kind(), f))
this.map(|ty| ty.kind()).fmt(f)
}
}

@@ -264,9 +264,12 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::RegionVid {
this: WithInfcx<'_, Infcx, &Self>,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
match this.infcx.universe_of_lt(*this.data) {
Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
match this.infcx {
None => write!(f, "{:?}", this.data),
Some(infcx) => match infcx.universe_of_lt(*this.data) {
Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
None => write!(f, "'?{}_..", this.data.index()),
},
}
}
}
19 changes: 11 additions & 8 deletions compiler/rustc_type_ir/src/const_kind.rs
Original file line number Diff line number Diff line change
@@ -180,15 +180,18 @@ impl<I: Interner> DebugWithInfcx<I> for InferConst {
this: WithInfcx<'_, Infcx, &Self>,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
match *this.data {
InferConst::Var(vid) => match this.infcx.universe_of_ct(vid) {
None => write!(f, "{:?}", this.data),
Some(universe) => write!(f, "?{}_{}c", vid.index(), universe.index()),
match this.infcx {
None => write!(f, "{:?}", this.data),
Some(infcx) => match *this.data {
InferConst::Var(vid) => match infcx.universe_of_ct(vid) {
None => write!(f, "?{}_..c", vid.index()),
Some(universe) => write!(f, "?{}_{}c", vid.index(), universe.index()),
},
InferConst::EffectVar(vid) => write!(f, "?{}e", vid.index()),
InferConst::Fresh(_) => {
unreachable!()
}
},
InferConst::EffectVar(vid) => write!(f, "?{}e", vid.index()),
InferConst::Fresh(_) => {
unreachable!()
}
}
}
}
50 changes: 27 additions & 23 deletions compiler/rustc_type_ir/src/debug.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,55 @@
use crate::{ConstVid, InferCtxtLike, Interner, TyVid, UniverseIndex};

use core::fmt;
use std::marker::PhantomData;

pub struct NoInfcx<I>(PhantomData<I>);

pub struct NoInfcx<I>(core::convert::Infallible, core::marker::PhantomData<I>);
impl<I: Interner> InferCtxtLike for NoInfcx<I> {
type Interner = I;

fn interner(&self) -> Self::Interner {
unreachable!()
match self.0 {}
}

fn universe_of_ty(&self, _ty: TyVid) -> Option<UniverseIndex> {
None
match self.0 {}
}

fn universe_of_lt(&self, _lt: I::InferRegion) -> Option<UniverseIndex> {
None
fn root_ty_var(&self, _vid: TyVid) -> TyVid {
match self.0 {}
}

fn universe_of_ct(&self, _ct: ConstVid) -> Option<UniverseIndex> {
None
fn probe_ty_var(&self, _vid: TyVid) -> Option<<Self::Interner as Interner>::Ty> {
match self.0 {}
}

fn root_ty_var(&self, vid: TyVid) -> TyVid {
vid
fn universe_of_lt(
&self,
_lt: <Self::Interner as Interner>::InferRegion,
) -> Option<UniverseIndex> {
match self.0 {}
}

fn probe_ty_var(&self, _vid: TyVid) -> Option<I::Ty> {
None
fn opportunistic_resolve_lt_var(
&self,
_vid: <Self::Interner as Interner>::InferRegion,
) -> Option<<Self::Interner as Interner>::Region> {
match self.0 {}
}

fn opportunistic_resolve_lt_var(&self, _vid: I::InferRegion) -> Option<I::Region> {
None
fn universe_of_ct(&self, _ct: ConstVid) -> Option<UniverseIndex> {
match self.0 {}
}

fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
vid
fn root_ct_var(&self, _vid: ConstVid) -> ConstVid {
match self.0 {}
}

fn probe_ct_var(&self, _vid: ConstVid) -> Option<I::Const> {
None
fn probe_ct_var(&self, _vid: ConstVid) -> Option<<Self::Interner as Interner>::Const> {
match self.0 {}
}

fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes {
Default::default()
match self.0 {}
}
}

@@ -96,7 +100,7 @@ impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for [T] {

pub struct WithInfcx<'a, Infcx: InferCtxtLike, T> {
pub data: T,
pub infcx: &'a Infcx,
pub infcx: Option<&'a Infcx>,
}

impl<Infcx: InferCtxtLike, T: Copy> Copy for WithInfcx<'_, Infcx, T> {}
@@ -109,13 +113,13 @@ impl<Infcx: InferCtxtLike, T: Clone> Clone for WithInfcx<'_, Infcx, T> {

impl<'a, I: Interner, T> WithInfcx<'a, NoInfcx<I>, T> {
pub fn with_no_infcx(data: T) -> Self {
Self { data, infcx: &NoInfcx(PhantomData) }
Self { data, infcx: None }
}
}

impl<'a, Infcx: InferCtxtLike, T> WithInfcx<'a, Infcx, T> {
pub fn new(data: T, infcx: &'a Infcx) -> Self {
Self { data, infcx }
Self { data, infcx: Some(infcx) }
}

pub fn wrap<U>(self, u: U) -> WithInfcx<'a, Infcx, U> {
2 changes: 2 additions & 0 deletions compiler/rustc_type_ir/src/interner.rs
Original file line number Diff line number Diff line change
@@ -29,6 +29,8 @@ pub trait Interner:
+ IrPrint<FnSig<Self>>
{
type DefId: Copy + Debug + Hash + Eq;
fn print_def_path(defid: Self::DefId, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;

type AdtDef: Copy + Debug + Hash + Eq;

type GenericArgs: GenericArgs<Self>;
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir/src/ir_print.rs
Original file line number Diff line number Diff line change
@@ -48,4 +48,4 @@ define_display_via_print!(
FnSig,
);

define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection);
define_debug_via_print!(ExistentialTraitRef, ExistentialProjection);
78 changes: 77 additions & 1 deletion compiler/rustc_type_ir/src/predicate.rs
Original file line number Diff line number Diff line change
@@ -40,6 +40,44 @@ pub struct TraitRef<I: Interner> {
_use_trait_ref_new_instead: (),
}

impl<I: Interner> fmt::Debug for TraitRef<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
}
}
impl<I: Interner> DebugWithInfcx<I> for TraitRef<I> {
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
// If we ever wind up with a malformed `TraitRef` it might be good to not ICE in its Debug impl(?)
if this.data.args.len() == 0 {
return f
.debug_tuple("TraitRef")
.field(&this.data.def_id)
.field(&this.data.args)
.finish();
}

write!(f, "({:?} as ", this.map(|trait_ref| trait_ref.args[0]))?;
I::print_def_path(this.data.def_id, f)?;

match this.data.args.len() {
0 => unreachable!(),
1 => write!(f, ")"), // the first arg is the self type
2 => write!(f, "<{:?}>)", this.map(|trait_ref| trait_ref.args[1])),
3.. => {
write!(f, "<{:?}", this.map(|trait_ref| trait_ref.args[1]))?;
for arg in &this.data.args[2..] {
let arg = this.wrap(arg);
write!(f, ", {:?}", arg)?;
}
write!(f, ">)")
}
}
}
}

impl<I: Interner> TraitRef<I> {
pub fn new(
interner: I,
@@ -114,8 +152,46 @@ impl<I: Interner> TraitPredicate<I> {

impl<I: Interner> fmt::Debug for TraitPredicate<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
WithInfcx::with_no_infcx(self).fmt(f)
}
}
impl<I: Interner> DebugWithInfcx<I> for TraitPredicate<I> {
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
// FIXME(effects) printing?
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)

// If we ever wind up with a malformed `TraitRef` it might be good to not ICE in its Debug impl(?)
if this.data.trait_ref.args.len() == 0 {
return f
.debug_tuple("TraitPredicate")
.field(&this.data.trait_ref.def_id)
.field(&this.data.trait_ref.args)
.field(&this.data.polarity)
.finish();
}

write!(f, "({:?}: ", this.map(|pred| pred.trait_ref.args[0]))?;
match this.data.polarity {
PredicatePolarity::Positive => (),
PredicatePolarity::Negative => write!(f, "!")?,
};
I::print_def_path(this.data.trait_ref.def_id, f)?;

match this.data.trait_ref.args.len() {
0 => unreachable!(),
1 => write!(f, ")"), // the first arg is the self type
2 => write!(f, "<{:?}>)", this.map(|trait_ref| trait_ref.trait_ref.args[1])),
3.. => {
write!(f, "<{:?}", this.map(|trait_ref| trait_ref.trait_ref.args[1]))?;
for arg in &this.data.trait_ref.args[2..] {
let arg = this.wrap(arg);
write!(f, ", {:?}", arg)?;
}
write!(f, ">)")
}
}
}
}

20 changes: 11 additions & 9 deletions compiler/rustc_type_ir/src/ty_kind.rs
Original file line number Diff line number Diff line change
@@ -415,7 +415,6 @@ impl<I: Interner> DebugWithInfcx<I> 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 {
WithInfcx::with_no_infcx(self).fmt(f)
@@ -924,15 +923,18 @@ impl<I: Interner> DebugWithInfcx<I> for InferTy {
this: WithInfcx<'_, Infcx, &Self>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match this.data {
InferTy::TyVar(vid) => {
if let Some(universe) = this.infcx.universe_of_ty(*vid) {
write!(f, "?{}_{}t", vid.index(), universe.index())
} else {
write!(f, "{:?}", this.data)
match this.infcx {
None => write!(f, "{:?}", this.data),
Some(infcx) => match this.data {
InferTy::TyVar(vid) => {
if let Some(universe) = infcx.universe_of_ty(*vid) {
write!(f, "?{}_{}t", vid.index(), universe.index())
} else {
write!(f, "{}_..t", vid.index())
}
}
}
_ => write!(f, "{:?}", this.data),
_ => write!(f, "{:?}", this.data),
},
}
}
}
2 changes: 1 addition & 1 deletion tests/ui/traits/cache-reached-depth-ice.rs
Original file line number Diff line number Diff line change
@@ -41,5 +41,5 @@ fn test<X: ?Sized + Send>() {}

fn main() {
test::<A>();
//~^ ERROR evaluate(Binder { value: TraitPredicate(<A as std::marker::Send>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk)
//~^ ERROR evaluate(Binder { value: (A: std::marker::Send), bound_vars: [] }) = Ok(EvaluatedToOk)
}
2 changes: 1 addition & 1 deletion tests/ui/traits/cache-reached-depth-ice.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: evaluate(Binder { value: TraitPredicate(<A as std::marker::Send>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk)
error: evaluate(Binder { value: (A: std::marker::Send), bound_vars: [] }) = Ok(EvaluatedToOk)
--> $DIR/cache-reached-depth-ice.rs:43:5
|
LL | fn test<X: ?Sized + Send>() {}
8 changes: 4 additions & 4 deletions tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs
Original file line number Diff line number Diff line change
@@ -57,10 +57,10 @@ fn main() {
// Key is that Vec<First> is "ok" and Third<'_, Ty> is "ok modulo regions":

forward();
//~^ ERROR evaluate(Binder { value: TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk)
//~| ERROR evaluate(Binder { value: TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions)
//~^ ERROR evaluate(Binder { value: (std::vec::Vec<First, std::alloc::Global>: std::marker::Unpin), bound_vars: [] }) = Ok(EvaluatedToOk)
//~| ERROR evaluate(Binder { value: (Third<'?0, Ty>: std::marker::Unpin), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions)

reverse();
//~^ ERROR evaluate(Binder { value: TraitPredicate(<std::vec::Vec<First> as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk)
//~| ERROR evaluate(Binder { value: TraitPredicate(<Third<'_, Ty> as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions)
//~^ ERROR evaluate(Binder { value: (std::vec::Vec<First, std::alloc::Global>: std::marker::Unpin), bound_vars: [] }) = Ok(EvaluatedToOk)
//~| ERROR evaluate(Binder { value: (Third<'?2, Ty>: std::marker::Unpin), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions)
}
Loading