Skip to content

Commit 1623ab0

Browse files
committed
Auto merge of rust-lang#107507 - BoxyUwU:deferred_projection_equality, r=lcnr
Implement `deferred_projection_equality` for erica solver Somewhat of a revival of rust-lang#96912. When relating projections now emit an `AliasEq` obligation instead of attempting to determine equality of projections that may not be as normalized as possible (i.e. because of lazy norm, or just containing inference variables that prevent us from resolving an impl). Only do this when the new solver is enabled
2 parents 5a8dfd9 + 4c98429 commit 1623ab0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+585
-163
lines changed

compiler/rustc_borrowck/src/type_check/relate_tys.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
1+
use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
22
use rustc_infer::infer::NllRegionVariableOrigin;
33
use rustc_infer::traits::PredicateObligations;
44
use rustc_middle::mir::ConstraintCategory;
@@ -140,10 +140,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
140140
);
141141
}
142142

143-
fn normalization() -> NormalizationStrategy {
144-
NormalizationStrategy::Eager
145-
}
146-
147143
fn forbid_inference_vars() -> bool {
148144
true
149145
}

compiler/rustc_hir_analysis/src/astconv/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13201320
ty::Clause::RegionOutlives(_) => bug!(),
13211321
},
13221322
ty::PredicateKind::WellFormed(_)
1323+
| ty::PredicateKind::AliasEq(..)
13231324
| ty::PredicateKind::ObjectSafe(_)
13241325
| ty::PredicateKind::ClosureKind(_, _, _)
13251326
| ty::PredicateKind::Subtype(_)

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

+1
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ fn trait_predicate_kind<'tcx>(
517517
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
518518
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
519519
| ty::PredicateKind::Clause(ty::Clause::Projection(_))
520+
| ty::PredicateKind::AliasEq(..)
520521
| ty::PredicateKind::WellFormed(_)
521522
| ty::PredicateKind::Subtype(_)
522523
| ty::PredicateKind::Coerce(_)

compiler/rustc_hir_analysis/src/outlives/explicit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
5555
ty::PredicateKind::Clause(ty::Clause::Trait(..))
5656
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
5757
| ty::PredicateKind::WellFormed(..)
58+
| ty::PredicateKind::AliasEq(..)
5859
| ty::PredicateKind::ObjectSafe(..)
5960
| ty::PredicateKind::ClosureKind(..)
6061
| ty::PredicateKind::Subtype(..)

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
669669
| ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
670670
| ty::PredicateKind::WellFormed(..)
671671
| ty::PredicateKind::ObjectSafe(..)
672+
| ty::PredicateKind::AliasEq(..)
672673
| ty::PredicateKind::ConstEvaluatable(..)
673674
| ty::PredicateKind::ConstEquate(..)
674675
// N.B., this predicate is created by breaking down a

compiler/rustc_hir_typeck/src/method/probe.rs

+1
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
837837
| ty::PredicateKind::ConstEvaluatable(..)
838838
| ty::PredicateKind::ConstEquate(..)
839839
| ty::PredicateKind::Ambiguous
840+
| ty::PredicateKind::AliasEq(..)
840841
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
841842
}
842843
});

compiler/rustc_infer/src/infer/canonical/query_response.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::infer::canonical::{
1212
Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
1313
QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
1414
};
15-
use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
15+
use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
1616
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
1717
use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
1818
use crate::traits::query::{Fallible, NoSolution};
@@ -717,10 +717,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
717717
});
718718
}
719719

720-
fn normalization() -> NormalizationStrategy {
721-
NormalizationStrategy::Eager
722-
}
723-
724720
fn forbid_inference_vars() -> bool {
725721
true
726722
}

compiler/rustc_infer/src/infer/combine.rs

+58-29
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
3838
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
3939
use rustc_middle::ty::subst::SubstsRef;
4040
use rustc_middle::ty::{
41-
self, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
42-
TypeVisitable,
41+
self, AliasKind, FallibleTypeFolder, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable,
42+
TypeSuperFoldable, TypeVisitable,
4343
};
4444
use rustc_middle::ty::{IntType, UintType};
4545
use rustc_span::{Span, DUMMY_SP};
@@ -74,7 +74,7 @@ impl<'tcx> InferCtxt<'tcx> {
7474
b: Ty<'tcx>,
7575
) -> RelateResult<'tcx, Ty<'tcx>>
7676
where
77-
R: TypeRelation<'tcx>,
77+
R: ObligationEmittingRelation<'tcx>,
7878
{
7979
let a_is_expected = relation.a_is_expected();
8080

@@ -122,6 +122,15 @@ impl<'tcx> InferCtxt<'tcx> {
122122
Err(TypeError::Sorts(ty::relate::expected_found(relation, a, b)))
123123
}
124124

125+
(ty::Alias(AliasKind::Projection, _), _) if self.tcx.trait_solver_next() => {
126+
relation.register_type_equate_obligation(a.into(), b.into());
127+
Ok(b)
128+
}
129+
(_, ty::Alias(AliasKind::Projection, _)) if self.tcx.trait_solver_next() => {
130+
relation.register_type_equate_obligation(b.into(), a.into());
131+
Ok(a)
132+
}
133+
125134
_ => ty::relate::super_relate_tys(relation, a, b),
126135
}
127136
}
@@ -133,7 +142,7 @@ impl<'tcx> InferCtxt<'tcx> {
133142
b: ty::Const<'tcx>,
134143
) -> RelateResult<'tcx, ty::Const<'tcx>>
135144
where
136-
R: ConstEquateRelation<'tcx>,
145+
R: ObligationEmittingRelation<'tcx>,
137146
{
138147
debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
139148
if a == b {
@@ -169,15 +178,15 @@ impl<'tcx> InferCtxt<'tcx> {
169178
// FIXME(#59490): Need to remove the leak check to accommodate
170179
// escaping bound variables here.
171180
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
172-
relation.const_equate_obligation(a, b);
181+
relation.register_const_equate_obligation(a, b);
173182
}
174183
return Ok(b);
175184
}
176185
(_, ty::ConstKind::Unevaluated(..)) if self.tcx.lazy_normalization() => {
177186
// FIXME(#59490): Need to remove the leak check to accommodate
178187
// escaping bound variables here.
179188
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
180-
relation.const_equate_obligation(a, b);
189+
relation.register_const_equate_obligation(a, b);
181190
}
182191
return Ok(a);
183192
}
@@ -435,32 +444,21 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
435444
Ok(Generalization { ty, needs_wf })
436445
}
437446

438-
pub fn add_const_equate_obligation(
447+
pub fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
448+
self.obligations.extend(obligations.into_iter());
449+
}
450+
451+
pub fn register_predicates(
439452
&mut self,
440-
a_is_expected: bool,
441-
a: ty::Const<'tcx>,
442-
b: ty::Const<'tcx>,
453+
obligations: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
443454
) {
444-
let predicate = if a_is_expected {
445-
ty::PredicateKind::ConstEquate(a, b)
446-
} else {
447-
ty::PredicateKind::ConstEquate(b, a)
448-
};
449-
self.obligations.push(Obligation::new(
450-
self.tcx(),
451-
self.trace.cause.clone(),
452-
self.param_env,
453-
ty::Binder::dummy(predicate),
454-
));
455+
self.obligations.extend(obligations.into_iter().map(|to_pred| {
456+
Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, to_pred)
457+
}))
455458
}
456459

457460
pub fn mark_ambiguous(&mut self) {
458-
self.obligations.push(Obligation::new(
459-
self.tcx(),
460-
self.trace.cause.clone(),
461-
self.param_env,
462-
ty::Binder::dummy(ty::PredicateKind::Ambiguous),
463-
));
461+
self.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]);
464462
}
465463
}
466464

@@ -779,11 +777,42 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
779777
}
780778
}
781779

782-
pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> {
780+
pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
781+
/// Register obligations that must hold in order for this relation to hold
782+
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>);
783+
784+
/// Register predicates that must hold in order for this relation to hold. Uses
785+
/// a default obligation cause, [`ObligationEmittingRelation::register_obligations`] should
786+
/// be used if control over the obligaton causes is required.
787+
fn register_predicates(
788+
&mut self,
789+
obligations: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
790+
);
791+
783792
/// Register an obligation that both constants must be equal to each other.
784793
///
785794
/// If they aren't equal then the relation doesn't hold.
786-
fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
795+
fn register_const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
796+
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
797+
798+
self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() {
799+
ty::PredicateKind::AliasEq(a.into(), b.into())
800+
} else {
801+
ty::PredicateKind::ConstEquate(a, b)
802+
})]);
803+
}
804+
805+
/// Register an obligation that both types must be equal to each other.
806+
///
807+
/// If they aren't equal then the relation doesn't hold.
808+
fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
809+
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
810+
811+
self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasEq(
812+
a.into(),
813+
b.into(),
814+
))]);
815+
}
787816
}
788817

789818
fn int_unification_error<'tcx>(

compiler/rustc_infer/src/infer/equate.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use super::combine::{CombineFields, ConstEquateRelation, RelationDir};
1+
use crate::traits::PredicateObligations;
2+
3+
use super::combine::{CombineFields, ObligationEmittingRelation, RelationDir};
24
use super::Subtype;
35

46
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
@@ -198,8 +200,15 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
198200
}
199201
}
200202

201-
impl<'tcx> ConstEquateRelation<'tcx> for Equate<'_, '_, 'tcx> {
202-
fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
203-
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
203+
impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> {
204+
fn register_predicates(
205+
&mut self,
206+
obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
207+
) {
208+
self.fields.register_predicates(obligations);
209+
}
210+
211+
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
212+
self.fields.register_obligations(obligations);
204213
}
205214
}

compiler/rustc_infer/src/infer/glb.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
//! Greatest lower bound. See [`lattice`].
22
3-
use super::combine::CombineFields;
3+
use super::combine::{CombineFields, ObligationEmittingRelation};
44
use super::lattice::{self, LatticeDir};
55
use super::InferCtxt;
66
use super::Subtype;
77

8-
use crate::infer::combine::ConstEquateRelation;
9-
use crate::traits::{ObligationCause, PredicateObligation};
8+
use crate::traits::{ObligationCause, PredicateObligations};
109
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
1110
use rustc_middle::ty::{self, Ty, TyCtxt};
1211

@@ -136,10 +135,6 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
136135
&self.fields.trace.cause
137136
}
138137

139-
fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
140-
self.fields.obligations.extend(obligations)
141-
}
142-
143138
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
144139
let mut sub = self.fields.sub(self.a_is_expected);
145140
sub.relate(v, a)?;
@@ -152,8 +147,15 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx,
152147
}
153148
}
154149

155-
impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> {
156-
fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
157-
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
150+
impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
151+
fn register_predicates(
152+
&mut self,
153+
obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
154+
) {
155+
self.fields.register_predicates(obligations);
156+
}
157+
158+
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
159+
self.fields.register_obligations(obligations);
158160
}
159161
}

compiler/rustc_infer/src/infer/lattice.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717
//!
1818
//! [lattices]: https://en.wikipedia.org/wiki/Lattice_(order)
1919
20+
use super::combine::ObligationEmittingRelation;
2021
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
2122
use super::InferCtxt;
2223

23-
use crate::traits::{ObligationCause, PredicateObligation};
24-
use rustc_middle::ty::relate::{RelateResult, TypeRelation};
24+
use crate::traits::ObligationCause;
25+
use rustc_middle::ty::relate::RelateResult;
2526
use rustc_middle::ty::TyVar;
2627
use rustc_middle::ty::{self, Ty};
2728

@@ -30,13 +31,11 @@ use rustc_middle::ty::{self, Ty};
3031
///
3132
/// GLB moves "down" the lattice (to smaller values); LUB moves
3233
/// "up" the lattice (to bigger values).
33-
pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> {
34+
pub trait LatticeDir<'f, 'tcx>: ObligationEmittingRelation<'tcx> {
3435
fn infcx(&self) -> &'f InferCtxt<'tcx>;
3536

3637
fn cause(&self) -> &ObligationCause<'tcx>;
3738

38-
fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
39-
4039
fn define_opaque_types(&self) -> bool;
4140

4241
// Relates the type `v` to `a` and `b` such that `v` represents
@@ -113,7 +112,7 @@ where
113112
| (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }))
114113
if this.define_opaque_types() && def_id.is_local() =>
115114
{
116-
this.add_obligations(
115+
this.register_obligations(
117116
infcx
118117
.handle_opaque_type(a, b, this.a_is_expected(), this.cause(), this.param_env())?
119118
.obligations,

compiler/rustc_infer/src/infer/lub.rs

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
//! Least upper bound. See [`lattice`].
22
3-
use super::combine::CombineFields;
3+
use super::combine::{CombineFields, ObligationEmittingRelation};
44
use super::lattice::{self, LatticeDir};
55
use super::InferCtxt;
66
use super::Subtype;
77

8-
use crate::infer::combine::ConstEquateRelation;
9-
use crate::traits::{ObligationCause, PredicateObligation};
8+
use crate::traits::{ObligationCause, PredicateObligations};
109
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
1110
use rustc_middle::ty::{self, Ty, TyCtxt};
1211

@@ -127,12 +126,6 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
127126
}
128127
}
129128

130-
impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> {
131-
fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
132-
self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
133-
}
134-
}
135-
136129
impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
137130
fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
138131
self.fields.infcx
@@ -142,10 +135,6 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
142135
&self.fields.trace.cause
143136
}
144137

145-
fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
146-
self.fields.obligations.extend(obligations)
147-
}
148-
149138
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
150139
let mut sub = self.fields.sub(self.a_is_expected);
151140
sub.relate(a, v)?;
@@ -157,3 +146,16 @@ impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx,
157146
self.fields.define_opaque_types
158147
}
159148
}
149+
150+
impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
151+
fn register_predicates(
152+
&mut self,
153+
obligations: impl IntoIterator<Item = impl ty::ToPredicate<'tcx>>,
154+
) {
155+
self.fields.register_predicates(obligations);
156+
}
157+
158+
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
159+
self.fields.register_obligations(obligations)
160+
}
161+
}

0 commit comments

Comments
 (0)