about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2020-01-18 07:59:16 -0500
committerNiko Matsakis <niko@alum.mit.edu>2020-02-06 15:58:01 -0500
commite9c78947dcd947709f41d52feaaf2eb6ea2711c8 (patch)
tree6d5bed3965a0f0c4f060bca7217ef909e2be7a56
parent5e0197f13a28d2b3d9aadbc6c5d48506ab4d696f (diff)
downloadrust-e9c78947dcd947709f41d52feaaf2eb6ea2711c8.tar.gz
rust-e9c78947dcd947709f41d52feaaf2eb6ea2711c8.zip
add the ability to skip leak check within a snapshot
The intention is that coherence code will skip the leak check and
determine whether two impls *would have* overlapped, and then issue a
warning.
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs10
-rw-r--r--src/librustc/infer/mod.rs27
-rw-r--r--src/librustc/infer/region_constraints/leak_check.rs12
3 files changed, 37 insertions, 12 deletions
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index bbca4823431..d25d186f4d7 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -128,6 +128,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         placeholder_map: &PlaceholderMap<'tcx>,
         snapshot: &CombinedSnapshot<'_, 'tcx>,
     ) -> RelateResult<'tcx, ()> {
+        // If the user gave `-Zno-leak-check`, or we have been
+        // configured to skip the leak check, then skip the leak check
+        // completely. The leak check is deprecated. Any legitimate
+        // subtyping errors that it would have caught will now be
+        // caught later on, during region checking. However, we
+        // continue to use it for a transition period.
+        if self.tcx.sess.opts.debugging_opts.no_leak_check || self.skip_leak_check.get() {
+            return Ok(());
+        }
+
         self.borrow_region_constraints().leak_check(
             self.tcx,
             overly_polymorphic,
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index f6edccc8ed7..35863a3a89a 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -125,6 +125,13 @@ pub struct InferCtxt<'a, 'tcx> {
     /// order, represented by its upper and lower bounds.
     pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
 
+    /// If set, this flag causes us to skip the 'leak check' during
+    /// higher-ranked subtyping operations. This flag is a temporary one used
+    /// to manage the removal of the leak-check: for the time being, we still run the
+    /// leak-check, but we issue warnings. This flag can only be set to true
+    /// when entering a snapshot.
+    skip_leak_check: Cell<bool>,
+
     /// Map from const parameter variable to the kind of const it represents.
     const_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::ConstVid<'tcx>>>>,
 
@@ -550,6 +557,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
                 tainted_by_errors_flag: Cell::new(false),
                 err_count_on_creation: tcx.sess.err_count(),
                 in_snapshot: Cell::new(false),
+                skip_leak_check: Cell::new(false),
                 region_obligations: RefCell::new(vec![]),
                 universe: Cell::new(ty::UniverseIndex::ROOT),
             })
@@ -593,6 +601,7 @@ pub struct CombinedSnapshot<'a, 'tcx> {
     region_obligations_snapshot: usize,
     universe: ty::UniverseIndex,
     was_in_snapshot: bool,
+    was_skip_leak_check: bool,
     _in_progress_tables: Option<Ref<'a, ty::TypeckTables<'tcx>>>,
 }
 
@@ -720,6 +729,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             region_obligations_snapshot: self.region_obligations.borrow().len(),
             universe: self.universe(),
             was_in_snapshot: in_snapshot,
+            was_skip_leak_check: self.skip_leak_check.get(),
             // Borrow tables "in progress" (i.e., during typeck)
             // to ban writes from within a snapshot to them.
             _in_progress_tables: self.in_progress_tables.map(|tables| tables.borrow()),
@@ -738,11 +748,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             region_obligations_snapshot,
             universe,
             was_in_snapshot,
+            was_skip_leak_check,
             _in_progress_tables,
         } = snapshot;
 
         self.in_snapshot.set(was_in_snapshot);
         self.universe.set(universe);
+        self.skip_leak_check.set(was_skip_leak_check);
 
         self.projection_cache.borrow_mut().rollback_to(projection_cache_snapshot);
         self.type_variables.borrow_mut().rollback_to(type_snapshot);
@@ -765,10 +777,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             region_obligations_snapshot: _,
             universe: _,
             was_in_snapshot,
+            was_skip_leak_check,
             _in_progress_tables,
         } = snapshot;
 
         self.in_snapshot.set(was_in_snapshot);
+        self.skip_leak_check.set(was_skip_leak_check);
 
         self.projection_cache.borrow_mut().commit(projection_cache_snapshot);
         self.type_variables.borrow_mut().commit(type_snapshot);
@@ -822,6 +836,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         r
     }
 
+    /// Execute `f` then unroll any bindings it creates.
+    pub fn skip_leak_check<R, F>(&self, f: F) -> R
+    where
+        F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
+    {
+        debug!("probe()");
+        let snapshot = self.start_snapshot();
+        self.skip_leak_check.set(true);
+        let r = f(&snapshot);
+        self.rollback_to("probe", snapshot);
+        r
+    }
+
     /// Scan the constraints produced since `snapshot` began and returns:
     ///
     /// - `None` -- if none of them involve "region outlives" constraints
diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc/infer/region_constraints/leak_check.rs
index 3b3a464ba55..29290cef2d2 100644
--- a/src/librustc/infer/region_constraints/leak_check.rs
+++ b/src/librustc/infer/region_constraints/leak_check.rs
@@ -33,18 +33,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
 
         assert!(self.in_snapshot());
 
-        // If the user gave `-Zno-leak-check`, then skip the leak
-        // check completely. This is wildly unsound and also not
-        // unlikely to cause an ICE or two. It is intended for use
-        // only during a transition period, in which the MIR typeck
-        // uses the "universe-style" check, and the rest of typeck
-        // uses the more conservative leak check.  Since the leak
-        // check is more conservative, we can't test the
-        // universe-style check without disabling it.
-        if tcx.sess.opts.debugging_opts.no_leak_check {
-            return Ok(());
-        }
-
         // Go through each placeholder that we created.
         for (_, &placeholder_region) in placeholder_map {
             // Find the universe this placeholder inhabits.