1
Fork 0

Rollup merge of #109462 - compiler-errors:alias-relate, r=BoxyUwU,lcnr

Make alias-eq have a relation direction (and rename it to alias-relate)

Emitting an "alias-eq" is too strict in some situations, since we don't always want strict equality between a projection and rigid ty. Adds a relation direction.

* I could probably just reuse this [`RelationDir`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/combine/enum.RelationDir.html) -- happy to uplift that struct into middle and use that instead, but I didn't feel compelled to... 🤷
* Some of the matching in `compute_alias_relate_goal` is a bit verbose -- I guess I could simplify it by using [`At::relate`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_infer/infer/at/struct.At.html#method.relate) and mapping the relation-dir to a variance.
* Alternatively, I coulld simplify things by making more helper functions on `EvalCtxt` (e.g. `EvalCtxt::relate_with_direction(T, T)` that also does the nested goal registration). No preference.

r? ```@lcnr``` cc ```@BoxyUwU``` though boxy can claim it if she wants
NOTE: first commit is all the changes, the second is just renaming stuff
This commit is contained in:
Matthias Krüger 2023-03-23 08:35:35 +01:00 committed by GitHub
commit 5d28853efe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 259 additions and 98 deletions

View file

@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> {
(_, ty::Alias(AliasKind::Projection, _)) | (ty::Alias(AliasKind::Projection, _), _)
if self.tcx.trait_solver_next() =>
{
relation.register_type_equate_obligation(a, b);
relation.register_type_relate_obligation(a, b);
Ok(a)
}
@ -842,23 +842,25 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> {
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() {
ty::PredicateKind::AliasEq(a.into(), b.into())
ty::PredicateKind::AliasRelate(a.into(), b.into(), ty::AliasRelationDirection::Equate)
} else {
ty::PredicateKind::ConstEquate(a, b)
})]);
}
/// Register an obligation that both types must be equal to each other.
///
/// If they aren't equal then the relation doesn't hold.
fn register_type_equate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasEq(
/// Register an obligation that both types must be related to each other according to
/// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`]
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
self.register_predicates([ty::Binder::dummy(ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
self.alias_relate_direction(),
))]);
}
/// Relation direction emitted for `AliasRelate` predicates, corresponding to the direction
/// of the relation.
fn alias_relate_direction(&self) -> ty::AliasRelationDirection;
}
fn int_unification_error<'tcx>(

View file

@ -210,4 +210,8 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Equate<'_, '_, 'tcx> {
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.fields.register_obligations(obligations);
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
ty::AliasRelationDirection::Equate
}
}

View file

@ -155,4 +155,9 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Glb<'_, '_, 'tcx> {
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.fields.register_obligations(obligations);
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
// FIXME(deferred_projection_equality): This isn't right, I think?
ty::AliasRelationDirection::Equate
}
}

View file

@ -155,4 +155,9 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.fields.register_obligations(obligations)
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
// FIXME(deferred_projection_equality): This isn't right, I think?
ty::AliasRelationDirection::Equate
}
}

View file

@ -711,6 +711,34 @@ where
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.delegate.register_obligations(obligations);
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
unreachable!("manually overridden to handle ty::Variance::Contravariant ambient variance")
}
fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Subtype,
),
// a :> b is b <: a
ty::Variance::Contravariant => ty::PredicateKind::AliasRelate(
b.into(),
a.into(),
ty::AliasRelationDirection::Subtype,
),
ty::Variance::Invariant => ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Equate,
),
// FIXME(deferred_projection_equality): Implement this when we trigger it.
// Probably just need to do nothing here.
ty::Variance::Bivariant => unreachable!(),
})]);
}
}
/// When we encounter a binder like `for<..> fn(..)`, we actually have

View file

@ -22,7 +22,7 @@ pub fn explicit_outlives_bounds<'tcx>(
ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
| ty::PredicateKind::AliasEq(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::WellFormed(..)

View file

@ -26,7 +26,7 @@ impl<'tcx> InferCtxt<'tcx> {
// completely change the normalization routine with the new solver.
//
// The new solver correctly handles projection equality so this hack
// is not necessary. if re-enabled it should emit `PredicateKind::AliasEq`
// is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate`
// not `PredicateKind::Clause(Clause::Projection(..))` as in the new solver
// `Projection` is used as `normalizes-to` which will fail for `<T as Trait>::Assoc eq ?0`.
return projection_ty.to_ty(self.tcx);

View file

@ -236,4 +236,8 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for Sub<'_, '_, 'tcx> {
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.fields.register_obligations(obligations);
}
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
ty::AliasRelationDirection::Subtype
}
}

View file

@ -293,7 +293,7 @@ impl<'tcx> Elaborator<'tcx> {
// Nothing to elaborate
}
ty::PredicateKind::Ambiguous => {}
ty::PredicateKind::AliasEq(..) => {
ty::PredicateKind::AliasRelate(..) => {
// No
}
ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {