Skip to content

Commit 5072b65

Browse files
Rebase fallout from TypeRelating::binders, inline higher_ranked_sub
1 parent b153656 commit 5072b65

File tree

2 files changed

+51
-66
lines changed

2 files changed

+51
-66
lines changed

compiler/rustc_infer/src/infer/relate/higher_ranked.rs

+3-62
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,11 @@
11
//! Helper routines for higher-ranked things. See the `doc` module at
22
//! the end of the file for details.
33
4-
use super::combine::CombineFields;
54
use crate::infer::CombinedSnapshot;
6-
use crate::infer::{HigherRankedType, InferCtxt};
5+
use crate::infer::InferCtxt;
76
use rustc_middle::ty::fold::FnMutDelegate;
8-
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
9-
use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable};
10-
11-
impl<'a, 'tcx> CombineFields<'a, 'tcx> {
12-
/// Checks whether `for<..> sub <: for<..> sup` holds.
13-
///
14-
/// For this to hold, **all** instantiations of the super type
15-
/// have to be a super type of **at least one** instantiation of
16-
/// the subtype.
17-
///
18-
/// This is implemented by first entering a new universe.
19-
/// We then replace all bound variables in `sup` with placeholders,
20-
/// and all bound variables in `sub` with inference vars.
21-
/// We can then just relate the two resulting types as normal.
22-
///
23-
/// Note: this is a subtle algorithm. For a full explanation, please see
24-
/// the [rustc dev guide][rd]
25-
///
26-
/// [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html
27-
#[instrument(skip(self), level = "debug")]
28-
pub fn higher_ranked_sub<T>(
29-
&mut self,
30-
sub: Binder<'tcx, T>,
31-
sup: Binder<'tcx, T>,
32-
sub_is_expected: bool,
33-
) -> RelateResult<'tcx, ()>
34-
where
35-
T: Relate<'tcx>,
36-
{
37-
let span = self.trace.cause.span;
38-
// First, we instantiate each bound region in the supertype with a
39-
// fresh placeholder region. Note that this automatically creates
40-
// a new universe if needed.
41-
self.infcx.enter_forall(sup, |sup_prime| {
42-
// Next, we instantiate each bound region in the subtype
43-
// with a fresh region variable. These region variables --
44-
// but no other preexisting region variables -- can name
45-
// the placeholders.
46-
let sub_prime =
47-
self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub);
48-
debug!("a_prime={:?}", sub_prime);
49-
debug!("b_prime={:?}", sup_prime);
50-
51-
// Compare types now that bound regions have been replaced.
52-
// Reorder the inputs so that the expected is passed first.
53-
let result = if sub_is_expected {
54-
self.sub().relate(sub_prime, sup_prime)
55-
} else {
56-
self.sup().relate(sup_prime, sub_prime)
57-
};
58-
59-
if result.is_ok() {
60-
debug!("OK result={result:?}");
61-
}
62-
// NOTE: returning the result here would be dangerous as it contains
63-
// placeholders which **must not** be named afterwards.
64-
result.map(|_| ())
65-
})
66-
}
67-
}
7+
use rustc_middle::ty::relate::RelateResult;
8+
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
689

6910
impl<'tcx> InferCtxt<'tcx> {
7011
/// Replaces all bound variables (lifetimes, types, and constants) bound by

compiler/rustc_infer/src/infer/relate/type_relating.rs

+48-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::combine::CombineFields;
2+
use crate::infer::BoundRegionConversionTime::HigherRankedType;
23
use crate::infer::{
34
DefineOpaqueTypes, ObligationEmittingRelation, StructurallyRelateAliases, SubregionOrigin,
45
};
@@ -214,16 +215,59 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
214215
{
215216
self.relate(a, b)?;
216217
} else {
218+
let span = self.fields.trace.cause.span;
219+
let infcx = self.fields.infcx;
220+
217221
match self.ambient_variance {
222+
// Checks whether `for<..> sub <: for<..> sup` holds.
223+
//
224+
// For this to hold, **all** instantiations of the super type
225+
// have to be a super type of **at least one** instantiation of
226+
// the subtype.
227+
//
228+
// This is implemented by first entering a new universe.
229+
// We then replace all bound variables in `sup` with placeholders,
230+
// and all bound variables in `sub` with inference vars.
231+
// We can then just relate the two resulting types as normal.
232+
//
233+
// Note: this is a subtle algorithm. For a full explanation, please see
234+
// the [rustc dev guide][rd]
235+
//
236+
// [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html
218237
ty::Covariant => {
219-
self.fields.higher_ranked_sub(a, b, true)?;
238+
infcx.enter_forall(b, |b| {
239+
let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
240+
self.relate(a, b)
241+
})?;
220242
}
221243
ty::Contravariant => {
222-
self.fields.higher_ranked_sub(b, a, false)?;
244+
infcx.enter_forall(a, |a| {
245+
let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
246+
self.relate(a, b)
247+
})?;
223248
}
249+
250+
// When **equating** binders, we check that there is a 1-to-1
251+
// correspondence between the bound vars in both types.
252+
//
253+
// We do so by separately instantiating one of the binders with
254+
// placeholders and the other with inference variables and then
255+
// equating the instantiated types.
256+
//
257+
// We want `for<..> A == for<..> B` -- therefore we want
258+
// `exists<..> A == for<..> B` and `exists<..> B == for<..> A`.
259+
// Check if `exists<..> A == for<..> B`
224260
ty::Invariant => {
225-
self.fields.higher_ranked_sub(a, b, true)?;
226-
self.fields.higher_ranked_sub(b, a, false)?;
261+
infcx.enter_forall(b, |b| {
262+
let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
263+
self.relate(a, b)
264+
})?;
265+
266+
// Check if `exists<..> B == for<..> A`.
267+
infcx.enter_forall(a, |a| {
268+
let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
269+
self.relate(a, b)
270+
})?;
227271
}
228272
ty::Bivariant => {
229273
unreachable!("Expected bivariance to be handled in relate_with_variance")

0 commit comments

Comments
 (0)