1
Fork 0

introduce enter_forall

This commit is contained in:
Boxy 2024-01-30 01:27:06 +00:00
parent af88f7db51
commit ac559af98f
15 changed files with 524 additions and 446 deletions

View file

@ -1032,10 +1032,10 @@ impl<'tcx> InferCtxt<'tcx> {
_ => {}
}
let ty::SubtypePredicate { a_is_expected, a, b } =
self.instantiate_binder_with_placeholders(predicate);
Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b))
// FIXME(tree_universes): leaking universes
self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b))
})
}
pub fn region_outlives_predicate(
@ -1043,10 +1043,13 @@ impl<'tcx> InferCtxt<'tcx> {
cause: &traits::ObligationCause<'tcx>,
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
) {
let ty::OutlivesPredicate(r_a, r_b) = self.instantiate_binder_with_placeholders(predicate);
let origin =
SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
// FIXME(tree_universes): leaking universes
self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
let origin = SubregionOrigin::from_obligation_cause(cause, || {
RelateRegionParamBound(cause.span)
});
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
})
}
/// Number of type variables created so far.
@ -1455,7 +1458,7 @@ impl<'tcx> InferCtxt<'tcx> {
// Use this method if you'd like to find some substitution of the binder's
// variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`]
// that corresponds to your use case, consider whether or not you should
// use [`InferCtxt::instantiate_binder_with_placeholders`] instead.
// use [`InferCtxt::enter_forall`] instead.
pub fn instantiate_binder_with_fresh_vars<T>(
&self,
span: Span,

View file

@ -38,24 +38,24 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
// First, we instantiate each bound region in the supertype with a
// fresh placeholder region. Note that this automatically creates
// a new universe if needed.
let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup);
self.infcx.enter_forall(sup, |sup_prime| {
// Next, we instantiate each bound region in the subtype
// with a fresh region variable. These region variables --
// but no other preexisting region variables -- can name
// the placeholders.
let sub_prime =
self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
debug!("a_prime={:?}", sub_prime);
debug!("b_prime={:?}", sup_prime);
// Next, we instantiate each bound region in the subtype
// with a fresh region variable. These region variables --
// but no other preexisting region variables -- can name
// the placeholders.
let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
debug!("a_prime={:?}", sub_prime);
debug!("b_prime={:?}", sup_prime);
// Compare types now that bound regions have been replaced.
let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?;
debug!("OK result={result:?}");
// NOTE: returning the result here would be dangerous as it contains
// placeholders which **must not** be named afterwards.
Ok(())
// Compare types now that bound regions have been replaced.
// FIXME(tree_universes): leaked dead universes
let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime);
if result.is_ok() {
debug!("OK result={result:?}");
}
result.map(|_| ())
})
}
}
@ -106,6 +106,14 @@ impl<'tcx> InferCtxt<'tcx> {
self.tcx.replace_bound_vars_uncached(binder, delegate)
}
pub fn enter_forall<T, U>(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U
where
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
let value = self.instantiate_binder_with_placeholders(forall);
f(value)
}
/// See [RegionConstraintCollector::leak_check][1]. We only check placeholder
/// leaking into `outer_universe`, i.e. placeholders which cannot be named by that
/// universe.

View file

@ -309,6 +309,18 @@ where
replaced
}
fn enter_forall<T, U>(
&mut self,
binder: ty::Binder<'tcx, T>,
f: impl FnOnce(&mut Self, T) -> U,
) -> U
where
T: ty::TypeFoldable<TyCtxt<'tcx>> + Copy,
{
let value = self.instantiate_binder_with_placeholders(binder);
f(self, value)
}
#[instrument(skip(self), level = "debug")]
fn instantiate_binder_with_existentials<T>(&mut self, binder: ty::Binder<'tcx, T>) -> T
where
@ -630,10 +642,10 @@ where
// Note: the order here is important. Create the placeholders first, otherwise
// we assign the wrong universe to the existential!
let b_replaced = self.instantiate_binder_with_placeholders(b);
let a_replaced = self.instantiate_binder_with_existentials(a);
self.relate(a_replaced, b_replaced)?;
self.enter_forall(b, |this, b| {
let a = this.instantiate_binder_with_existentials(a);
this.relate(a, b)
})?;
self.ambient_variance = variance;
}
@ -650,10 +662,10 @@ where
let variance =
std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant);
let a_replaced = self.instantiate_binder_with_placeholders(a);
let b_replaced = self.instantiate_binder_with_existentials(b);
self.relate(a_replaced, b_replaced)?;
self.enter_forall(a, |this, a| {
let b = this.instantiate_binder_with_existentials(b);
this.relate(a, b)
})?;
self.ambient_variance = variance;
}