about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs43
1 files changed, 42 insertions, 1 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 91dbbfb4973..6f2fe8bddb2 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -72,7 +72,7 @@ pub struct RegionInferenceContext<'tcx> {
     /// The SCC computed from `constraints` and the constraint
     /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
     /// compute the values of each region.
-    pub constraint_sccs: Rc<ConstraintSccs>,
+    constraint_sccs: Rc<ConstraintSccs>,
 
     /// Reverse of the SCC constraint graph --  i.e., an edge `A -> B` exists if
     /// `B: A`. This is used to compute the universal regions that are required
@@ -397,6 +397,39 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// and (b) any universally quantified regions that it outlives,
     /// which in this case is just itself. R1 (`'b`) in contrast also
     /// outlives `'a` and hence contains R0 and R1.
+    ///
+    /// This bit of logic also handles invalid universe relations
+    /// for higher-kinded types.
+    ///
+    // We Walk each SCC `A` and `B` such that `A: B`
+    // and ensure that universe(A) can see universe(B).
+    //
+    // This serves to enforce the 'empty/placeholder' hierarchy
+    // (described in more detail on `RegionKind`):
+    //
+    // ```
+    // static -----+
+    //   |         |
+    // empty(U0) placeholder(U1)
+    //   |      /
+    // empty(U1)
+    // ```
+    //
+    // In particular, imagine we have variables R0 in U0 and R1
+    // created in U1, and constraints like this;
+    //
+    // ```
+    // R1: !1 // R1 outlives the placeholder in U1
+    // R1: R0 // R1 outlives R0
+    // ```
+    //
+    // Here, we wish for R1 to be `'static`, because it
+    // cannot outlive `placeholder(U1)` and `empty(U0)` any other way.
+    //
+    // Thanks to this loop, what happens is that the `R1: R0`
+    // constraint has lowered the universe of `R1` to `U0`, which in turn
+    // means that the `R1: !1` constraint here will cause
+    // `R1` to become `'static`.
     fn init_free_and_bound_regions(&mut self) {
         // Update the names (if any)
         // This iterator has unstable order but we collect it all into an IndexVec
@@ -1412,6 +1445,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
+    /// The minimum universe of any variable reachable from this
+    /// SCC, inside or outside of it.
     fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
         self.constraint_sccs().annotation(scc).universe()
     }
@@ -2151,6 +2186,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
     /// Returns the representative `RegionVid` for a given SCC.
     /// See `RegionTracker` for how a region variable ID is chosen.
+    ///
+    /// It is a hacky way to manage checking regions for equality,
+    /// since we can 'canonicalize' each region to the representative
+    /// of its SCC and be sure that -- if they have the same repr --
+    /// they *must* be equal (though not having the same repr does not
+    /// mean they are unequal).
     fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid {
         self.constraint_sccs.annotation(scc).representative
     }