1
Fork 0

update higher_ranked_sub docs

This commit is contained in:
lcnr 2022-06-02 13:37:09 +02:00
parent 54fac386a4
commit e61807c6bf
3 changed files with 35 additions and 27 deletions

View file

@ -153,12 +153,12 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
{
if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
self.fields.higher_ranked_sub(b, a, self.a_is_expected)
self.fields.higher_ranked_sub(b, a, self.a_is_expected)?;
} else {
// Fast path for the common case.
self.relate(a.skip_binder(), b.skip_binder())?;
Ok(a)
}
Ok(a)
}
}

View file

@ -9,49 +9,56 @@ use rustc_middle::ty::{self, Binder, TypeFoldable};
use std::cell::Cell;
impl<'a, 'tcx> CombineFields<'a, 'tcx> {
/// Checks whether `for<..> sub <: for<..> sup` holds.
///
/// For this to hold, **all** instantiations of the super type
/// have to be a super type of **at least one** instantiation of
/// the subtype.
///
/// This is implemented by first entering a new universe.
/// We then replace all bound variables in `sup` with placeholders,
/// and all bound variables in `sup` with inference vars.
/// We can then just relate the two resulting types as normal.
///
/// Note: this is a subtle algorithm. For a full explanation, please see
/// the [rustc dev guide][rd]
///
/// [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html
#[instrument(skip(self), level = "debug")]
pub fn higher_ranked_sub<T>(
&mut self,
a: Binder<'tcx, T>,
b: Binder<'tcx, T>,
a_is_expected: bool,
) -> RelateResult<'tcx, Binder<'tcx, T>>
sub: Binder<'tcx, T>,
sup: Binder<'tcx, T>,
sub_is_expected: bool,
) -> RelateResult<'tcx, ()>
where
T: Relate<'tcx>,
{
// Rather than checking the subtype relationship between `a` and `b`
// as-is, we need to do some extra work here in order to make sure
// that function subtyping works correctly with respect to regions
//
// Note: this is a subtle algorithm. For a full explanation, please see
// the rustc dev guide:
// <https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html>
let span = self.trace.cause.span;
self.infcx.commit_if_ok(|_| {
// First, we instantiate each bound region in the supertype with a
// fresh placeholder region.
let b_prime = self.infcx.replace_bound_vars_with_placeholders(b);
// fresh placeholder region. Note that this automatically creates
// a new universe if needed.
let sup_prime = self.infcx.replace_bound_vars_with_placeholders(sup);
// Next, we instantiate each bound region in the subtype
// with a fresh region variable. These region variables --
// but no other pre-existing region variables -- can name
// the placeholders.
let a_prime = self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, a);
let sub_prime =
self.infcx.replace_bound_vars_with_fresh_vars(span, HigherRankedType, sub);
debug!("a_prime={:?}", a_prime);
debug!("b_prime={:?}", b_prime);
debug!("a_prime={:?}", sub_prime);
debug!("b_prime={:?}", sup_prime);
// Compare types now that bound regions have been replaced.
let result = self.sub(a_is_expected).relate(a_prime, b_prime)?;
let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?;
debug!("higher_ranked_sub: OK result={:?}", result);
// We related `a_prime` and `b_prime`, which just had any bound vars
// replaced with placeholders or infer vars, respectively. Relating
// them should not introduce new bound vars.
Ok(ty::Binder::dummy(result))
debug!("higher_ranked_sub: OK result={result:?}");
// NOTE: returning the result here would be dangerous as it contains
// placeholders which **must not** be named after wards.
Ok(())
})
}
}

View file

@ -198,7 +198,8 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
where
T: Relate<'tcx>,
{
self.fields.higher_ranked_sub(a, b, self.a_is_expected)
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
Ok(a)
}
}