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

emit ProjectionPredicate obligations when relating projections #96912

Closed
wants to merge 3 commits into from
Closed
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
8 changes: 8 additions & 0 deletions compiler/rustc_borrowck/src/type_check/relate_tys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
// 'static.
fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {}

fn projection_equate(&mut self, _projection_ty: ty::ProjectionTy<'tcx>, _ty: Ty<'tcx>) {
unreachable!()
}

fn defer_projection_equality(&self) -> bool {
false
}

fn normalization() -> NormalizationStrategy {
NormalizationStrategy::Eager
}
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0275.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ trait Foo {}
struct Bar<T>(T);

impl<T> Foo for T where Bar<T>: Foo {}

fn takes_foo<T: Foo>() {}

fn calls_takes_foo() {
takes_foo::<()>();
}
```

This error occurs when there was a recursive trait requirement that overflowed
Expand Down
41 changes: 36 additions & 5 deletions compiler/rustc_infer/src/infer/at.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub struct At<'a, 'tcx> {
/// matching from matching anything against opaque
/// types.
pub define_opaque_types: bool,
pub defer_projection_equality: bool,
}

pub struct Trace<'a, 'tcx> {
Expand All @@ -55,7 +56,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
cause: &'a ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> At<'a, 'tcx> {
At { infcx: self, cause, param_env, define_opaque_types: true }
At {
infcx: self,
cause,
param_env,
define_opaque_types: true,
defer_projection_equality: true,
}
}

/// Forks the inference context, creating a new inference context with the same inference
Expand Down Expand Up @@ -101,6 +108,10 @@ impl<'a, 'tcx> At<'a, 'tcx> {
Self { define_opaque_types, ..self }
}

pub fn defer_projection_equality(self, defer_projection_equality: bool) -> Self {
Self { defer_projection_equality, ..self }
}

/// Hacky routine for equating two impl headers in coherence.
pub fn eq_impl_headers(
self,
Expand Down Expand Up @@ -252,7 +263,12 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
{
let Trace { at, trace, a_is_expected } = self;
at.infcx.commit_if_ok(|_| {
let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
let mut fields = at.infcx.combine_fields(
trace,
at.param_env,
at.define_opaque_types,
at.defer_projection_equality,
);
fields
.sub(a_is_expected)
.relate(a, b)
Expand All @@ -269,7 +285,12 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
{
let Trace { at, trace, a_is_expected } = self;
at.infcx.commit_if_ok(|_| {
let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
let mut fields = at.infcx.combine_fields(
trace,
at.param_env,
at.define_opaque_types,
at.defer_projection_equality,
);
fields
.equate(a_is_expected)
.relate(a, b)
Expand All @@ -284,7 +305,12 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
{
let Trace { at, trace, a_is_expected } = self;
at.infcx.commit_if_ok(|_| {
let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
let mut fields = at.infcx.combine_fields(
trace,
at.param_env,
at.define_opaque_types,
at.defer_projection_equality,
);
fields
.lub(a_is_expected)
.relate(a, b)
Expand All @@ -299,7 +325,12 @@ impl<'a, 'tcx> Trace<'a, 'tcx> {
{
let Trace { at, trace, a_is_expected } = self;
at.infcx.commit_if_ok(|_| {
let mut fields = at.infcx.combine_fields(trace, at.param_env, at.define_opaque_types);
let mut fields = at.infcx.combine_fields(
trace,
at.param_env,
at.define_opaque_types,
at.defer_projection_equality,
);
fields
.glb(a_is_expected)
.relate(a, b)
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,23 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
span_bug!(self.cause.span(), "generic_const_exprs: unreachable `const_equate`");
}

fn projection_equate(&mut self, projection_ty: ty::ProjectionTy<'tcx>, ty: Ty<'tcx>) {
self.obligations.push(Obligation {
cause: self.cause.clone(),
param_env: self.param_env,
predicate: ty::Binder::dummy(ty::PredicateKind::Projection(ty::ProjectionPredicate {
projection_ty,
term: ty::Term::from(ty),
}))
.to_predicate(self.infcx.tcx),
recursion_depth: 0,
})
}

fn defer_projection_equality(&self) -> bool {
true
}

fn normalization() -> NormalizationStrategy {
NormalizationStrategy::Eager
}
Expand Down
38 changes: 38 additions & 0 deletions compiler/rustc_infer/src/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub struct CombineFields<'infcx, 'tcx> {
/// matching from matching anything against opaque
/// types.
pub define_opaque_types: bool,
pub defer_projection_equality: bool,
}

#[derive(Copy, Clone, Debug)]
Expand Down Expand Up @@ -457,6 +458,19 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
ty::Binder::dummy(predicate).to_predicate(self.tcx()),
));
}

pub fn add_projection_equate_obligation(
&mut self,
projection_ty: ty::ProjectionTy<'tcx>,
ty: Ty<'tcx>,
) {
self.obligations.push(Obligation::new(
self.trace.cause.clone(),
self.param_env,
ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, term: ty::Term::from(ty) })
.to_predicate(self.tcx()),
));
}
}

struct Generalizer<'cx, 'tcx> {
Expand Down Expand Up @@ -759,6 +773,18 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
_ => relate::super_relate_consts(self, c, c),
}
}

fn projection_equate_obligation(
&mut self,
_projection_ty: ty::ProjectionTy<'tcx>,
_ty: Ty<'tcx>,
) {
bug!("`TypeGeneralizer` shouldn't equate projections with other kinds of types");
}

fn defer_projection_equality(&self) -> bool {
false
}
}

pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> {
Expand Down Expand Up @@ -982,4 +1008,16 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
_ => relate::super_relate_consts(self, c, c),
}
}

fn projection_equate_obligation(
&mut self,
_projection_ty: ty::ProjectionTy<'tcx>,
_ty: Ty<'tcx>,
) {
bug!("`ConstInferUnifier` shouldn't equate projections with other kinds of types");
}

fn defer_projection_equality(&self) -> bool {
bug!("`ConstInferUnifier` shouldn't equate projections with other kinds of types");
}
}
12 changes: 12 additions & 0 deletions compiler/rustc_infer/src/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,18 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
}
Ok(a)
}

fn projection_equate_obligation(
&mut self,
projection_ty: ty::ProjectionTy<'tcx>,
ty: Ty<'tcx>,
) {
self.fields.add_projection_equate_obligation(projection_ty, ty);
}

fn defer_projection_equality(&self) -> bool {
self.fields.defer_projection_equality
}
}

impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> {
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2777,6 +2777,18 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
// relation
Ok(a)
}

fn projection_equate_obligation(
&mut self,
_projection_ty: ty::ProjectionTy<'tcx>,
_ty: Ty<'tcx>,
) {
unreachable!()
}

fn defer_projection_equality(&self) -> bool {
false
}
}

impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_infer/src/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
}
}

fn projection_equate_obligation(
&mut self,
projection_ty: ty::ProjectionTy<'tcx>,
ty: Ty<'tcx>,
) {
self.fields.add_projection_equate_obligation(projection_ty, ty);
}

fn defer_projection_equality(&self) -> bool {
self.fields.defer_projection_equality
}
}

impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> {
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_infer/src/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,18 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
}
}

fn projection_equate_obligation(
&mut self,
projection_ty: ty::ProjectionTy<'tcx>,
ty: Ty<'tcx>,
) {
self.fields.add_projection_equate_obligation(projection_ty, ty);
}

fn defer_projection_equality(&self) -> bool {
self.fields.defer_projection_equality
}
}

impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
trace: TypeTrace<'tcx>,
param_env: ty::ParamEnv<'tcx>,
define_opaque_types: bool,
defer_projection_equality: bool,
) -> CombineFields<'a, 'tcx> {
CombineFields {
infcx: self,
Expand All @@ -792,6 +793,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
param_env,
obligations: PredicateObligations::new(),
define_opaque_types,
defer_projection_equality,
}
}

Expand Down
Loading