woops, soundly generalizing is hard

I ended up getting confused while trying to flip the
variances when flipping the order. Should be
all right now
This commit is contained in:
lcnr 2024-02-22 22:18:43 +01:00
parent 1bb3a9f67a
commit fa2921bdca
2 changed files with 33 additions and 23 deletions

View File

@ -123,7 +123,11 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
// `handle_opaque_type` cannot handle subtyping, so to support subtyping // `handle_opaque_type` cannot handle subtyping, so to support subtyping
// we instead eagerly generalize here. This is a bit of a mess but will go // we instead eagerly generalize here. This is a bit of a mess but will go
// away once we're using the new solver. // away once we're using the new solver.
let mut enable_subtyping = |ty, ty_is_expected| { //
// Given `opaque rel B`, we create a new infer var `ty_vid` constrain it
// by using `ty_vid rel B` and then finally and end by equating `ty_vid` to
// the opaque.
let mut enable_subtyping = |ty, opaque_is_expected| {
let ty_vid = infcx.next_ty_var_id_in_universe( let ty_vid = infcx.next_ty_var_id_in_universe(
TypeVariableOrigin { TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable, kind: TypeVariableOriginKind::MiscVariable,
@ -132,7 +136,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
ty::UniverseIndex::ROOT, ty::UniverseIndex::ROOT,
); );
let variance = if ty_is_expected { let variance = if opaque_is_expected {
self.ambient_variance self.ambient_variance
} else { } else {
self.ambient_variance.xform(ty::Contravariant) self.ambient_variance.xform(ty::Contravariant)
@ -140,7 +144,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
self.type_checker.infcx.instantiate_ty_var( self.type_checker.infcx.instantiate_ty_var(
self, self,
ty_is_expected, opaque_is_expected,
ty_vid, ty_vid,
variance, variance,
ty, ty,
@ -149,8 +153,8 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
}; };
let (a, b) = match (a.kind(), b.kind()) { let (a, b) = match (a.kind(), b.kind()) {
(&ty::Alias(ty::Opaque, ..), _) => (a, enable_subtyping(b, false)?), (&ty::Alias(ty::Opaque, ..), _) => (a, enable_subtyping(b, true)?),
(_, &ty::Alias(ty::Opaque, ..)) => (enable_subtyping(a, true)?, b), (_, &ty::Alias(ty::Opaque, ..)) => (enable_subtyping(a, false)?, b),
_ => unreachable!( _ => unreachable!(
"expected at least one opaque type in `relate_opaques`, got {a} and {b}." "expected at least one opaque type in `relate_opaques`, got {a} and {b}."
), ),

View File

@ -26,13 +26,13 @@ impl<'tcx> InferCtxt<'tcx> {
/// This is *not* expected to be used anywhere except for an implementation of /// This is *not* expected to be used anywhere except for an implementation of
/// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all /// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
/// other usecases (i.e. setting the value of a type var). /// other usecases (i.e. setting the value of a type var).
#[instrument(level = "debug", skip(self, relation, target_is_expected))] #[instrument(level = "debug", skip(self, relation))]
pub fn instantiate_ty_var<R: ObligationEmittingRelation<'tcx>>( pub fn instantiate_ty_var<R: ObligationEmittingRelation<'tcx>>(
&self, &self,
relation: &mut R, relation: &mut R,
target_is_expected: bool, target_is_expected: bool,
target_vid: ty::TyVid, target_vid: ty::TyVid,
ambient_variance: ty::Variance, instantiation_variance: ty::Variance,
source_ty: Ty<'tcx>, source_ty: Ty<'tcx>,
) -> RelateResult<'tcx, ()> { ) -> RelateResult<'tcx, ()> {
debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown()); debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
@ -46,7 +46,7 @@ impl<'tcx> InferCtxt<'tcx> {
// //
// We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`. // We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`.
let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } =
self.generalize(relation.span(), target_vid, ambient_variance, source_ty)?; self.generalize(relation.span(), target_vid, instantiation_variance, source_ty)?;
// Constrain `b_vid` to the generalized type `generalized_ty`. // Constrain `b_vid` to the generalized type `generalized_ty`.
if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() { if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
@ -73,7 +73,7 @@ impl<'tcx> InferCtxt<'tcx> {
// the alias can be normalized to something which does not // the alias can be normalized to something which does not
// mention `?0`. // mention `?0`.
if self.next_trait_solver() { if self.next_trait_solver() {
let (lhs, rhs, direction) = match ambient_variance { let (lhs, rhs, direction) = match instantiation_variance {
ty::Variance::Invariant => { ty::Variance::Invariant => {
(generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate) (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate)
} }
@ -106,22 +106,28 @@ impl<'tcx> InferCtxt<'tcx> {
} }
} }
} else { } else {
// HACK: make sure that we `a_is_expected` continues to be // NOTE: The `instantiation_variance` is not the same variance as
// correct when relating the generalized type with the source. // used by the relation. When instantiating `b`, `target_is_expected`
// is flipped and the `instantion_variance` is also flipped. To
// constrain the `generalized_ty` while using the original relation,
// we therefore only have to flip the arguments.
//
// ```ignore
// ?a rel B
// instantiate_ty_var(?a, B) # expected and variance not flipped
// B' rel B
// ```
// or
// ```ignore
// A rel ?b
// instantiate_ty_var(?b, A) # expected and variance flipped
// A rel A'
// ```
if target_is_expected == relation.a_is_expected() { if target_is_expected == relation.a_is_expected() {
relation.relate_with_variance( relation.relate(generalized_ty, source_ty)?;
ambient_variance,
ty::VarianceDiagInfo::default(),
generalized_ty,
source_ty,
)?;
} else { } else {
relation.relate_with_variance( debug!("flip relation");
ambient_variance.xform(ty::Contravariant), relation.relate(source_ty, generalized_ty)?;
ty::VarianceDiagInfo::default(),
source_ty,
generalized_ty,
)?;
} }
} }