about summary refs log tree commit diff
diff options
context:
space:
mode:
authorlcnr <rust@lcnr.de>2022-06-02 13:37:09 +0200
committerlcnr <rust@lcnr.de>2022-06-10 10:09:50 +0200
commite61807c6bf1f99ca9dd0418ca7e862f0b364f0c6 (patch)
tree6870b65b14474e47ccb856954e64c7628238f373
parent54fac386a42b466b747c1611568a787f38b06432 (diff)
downloadrust-e61807c6bf1f99ca9dd0418ca7e862f0b364f0c6.tar.gz
rust-e61807c6bf1f99ca9dd0418ca7e862f0b364f0c6.zip
update higher_ranked_sub docs
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs4
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs55
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs3
3 files changed, 35 insertions, 27 deletions
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index ef6d464d3c6..3b1798ca737 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -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)
     }
 }
 
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index 77b3ccbc4ea..017f265331c 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -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)?;
-
-            debug!("higher_ranked_sub: OK result={:?}", result);
+            let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?;
 
-            // 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(())
         })
     }
 }
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index 3600b54a271..d0c6d8d16eb 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -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)
     }
 }