]> git.lizzy.rs Git - rust.git/commitdiff
eagerly check whether we replace any bound vars
authorlcnr <rust@lcnr.de>
Wed, 8 Jun 2022 16:45:49 +0000 (18:45 +0200)
committerlcnr <rust@lcnr.de>
Fri, 10 Jun 2022 08:09:50 +0000 (10:09 +0200)
compiler/rustc_infer/src/infer/higher_ranked/mod.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_typeck/src/check/method/confirm.rs

index 017f265331c1691f5b34f2184029004288b9dc90..bb3b410b2bde3258203439f7b0fac269aa29dbf1 100644 (file)
@@ -6,7 +6,6 @@
 use crate::infer::CombinedSnapshot;
 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::{self, Binder, TypeFoldable};
-use std::cell::Cell;
 
 impl<'a, 'tcx> CombineFields<'a, 'tcx> {
     /// Checks whether `for<..> sub <: for<..> sup` holds.
@@ -57,7 +56,7 @@ pub fn higher_ranked_sub<T>(
 
             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.
+            // placeholders which **must not** be named afterwards.
             Ok(())
         })
     }
@@ -65,7 +64,9 @@ pub fn higher_ranked_sub<T>(
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// Replaces all bound variables (lifetimes, types, and constants) bound by
-    /// `binder` with placeholder variables.
+    /// `binder` with placeholder variables in a new universe. This means that the
+    /// new placeholders can only be named by inference variables created after
+    /// this method has been called.
     ///
     /// This is the first step of checking subtyping when higher-ranked things are involved.
     /// For more details visit the relevant sections of the [rustc dev guide].
@@ -74,18 +75,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     pub fn replace_bound_vars_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T>) -> T
     where
-        T: TypeFoldable<'tcx>,
+        T: TypeFoldable<'tcx> + Copy,
     {
-        // Figure out what the next universe will be, but don't actually create
-        // it until after we've done the substitution (in particular there may
-        // be no bound variables). This is a performance optimization, since the
-        // leak check for example can be skipped if no new universes are created
-        // (i.e., if there are no placeholders).
-        let next_universe = self.universe().next_universe();
+        if let Some(inner) = binder.no_bound_vars() {
+            return inner;
+        }
+
+        let next_universe = self.create_next_universe();
 
-        let replaced_bound_var = Cell::new(false);
         let fld_r = |br: ty::BoundRegion| {
-            replaced_bound_var.set(true);
             self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
                 universe: next_universe,
                 name: br.kind,
@@ -93,7 +91,6 @@ pub fn replace_bound_vars_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T
         };
 
         let fld_t = |bound_ty: ty::BoundTy| {
-            replaced_bound_var.set(true);
             self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
                 universe: next_universe,
                 name: bound_ty.var,
@@ -101,7 +98,6 @@ pub fn replace_bound_vars_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T
         };
 
         let fld_c = |bound_var: ty::BoundVar, ty| {
-            replaced_bound_var.set(true);
             self.tcx.mk_const(ty::ConstS {
                 val: ty::ConstKind::Placeholder(ty::PlaceholderConst {
                     universe: next_universe,
@@ -112,16 +108,7 @@ pub fn replace_bound_vars_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T
         };
 
         let result = self.tcx.replace_bound_vars_uncached(binder, fld_r, fld_t, fld_c);
-
-        // If there were higher-ranked regions to replace, then actually create
-        // the next universe (this avoids needlessly creating universes).
-        if replaced_bound_var.get() {
-            let n_u = self.create_next_universe();
-            assert_eq!(n_u, next_universe);
-        }
-
         debug!(?next_universe, ?result);
-
         result
     }
 
index 42bd96acd7c47a593289ab609bdaba34394050f1..30b75e9ae7562dbd7eb2af20e95ce7962f7b1a7f 100644 (file)
@@ -1526,8 +1526,12 @@ pub fn replace_bound_vars_with_fresh_vars<T>(
         value: ty::Binder<'tcx, T>,
     ) -> T
     where
-        T: TypeFoldable<'tcx>,
+        T: TypeFoldable<'tcx> + Copy,
     {
+        if let Some(inner) = value.no_bound_vars() {
+            return inner;
+        }
+
         let mut region_map = BTreeMap::new();
         let fld_r = |br: ty::BoundRegion| {
             *region_map
index 2a9a5615ca96301fbfe3183fb89426a584017806..4061b7cae7c78348384d8050d226ef85162ecbb5 100644 (file)
@@ -572,7 +572,7 @@ fn upcast(
 
     fn replace_bound_vars_with_fresh_vars<T>(&self, value: ty::Binder<'tcx, T>) -> T
     where
-        T: TypeFoldable<'tcx>,
+        T: TypeFoldable<'tcx> + Copy,
     {
         self.fcx.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, value)
     }