]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_infer/infer/mod.rs
Fix review comments
[rust.git] / src / librustc_infer / infer / mod.rs
index ed99b47f80c7c1bb86510484d38111ab0b56c531..67d330ac89255ac576de1e9dd37609d317a46d35 100644 (file)
@@ -6,13 +6,14 @@
 pub use self::SubregionOrigin::*;
 pub use self::ValuePairs::*;
 
+pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog};
+
 use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine};
 
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::snapshot_vec as sv;
 use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::undo_log::{Rollback, Snapshots, UndoLogs};
+use rustc_data_structures::undo_log::Rollback;
 use rustc_data_structures::unify as ut;
 use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
@@ -38,7 +39,6 @@
 use std::cell::{Cell, Ref, RefCell};
 use std::collections::BTreeMap;
 use std::fmt;
-use std::marker::PhantomData;
 
 use self::combine::CombineFields;
 use self::free_regions::RegionRelations;
@@ -69,6 +69,7 @@
 pub mod resolve;
 mod sub;
 pub mod type_variable;
+mod undo_log;
 
 use crate::infer::canonical::OriginalQueryValues;
 pub use rustc_middle::infer::unify_key;
@@ -85,6 +86,10 @@ pub struct InferOk<'tcx, T> {
 pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
 pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result"
 
+pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable<
+    ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut InferCtxtUndoLogs<'tcx>>,
+>;
+
 /// How we should handle region solving.
 ///
 /// This is used so that the region values inferred by HIR region solving are
@@ -141,22 +146,21 @@ pub struct InferCtxtInner<'tcx> {
     /// Cache for projections. This cache is snapshotted along with the infcx.
     ///
     /// Public so that `traits::project` can use it.
-    pub projection_cache: traits::ProjectionCache<'tcx>,
+    pub projection_cache: traits::ProjectionCacheStorage<'tcx>,
 
     /// We instantiate `UnificationTable` with `bounds<Ty>` because the types
     /// that might instantiate a general type variable have an order,
     /// represented by its upper and lower bounds.
-    type_variables: type_variable::TypeVariableStorage<'tcx>,
-    undo_log: Logs<'tcx>,
+    type_variable_storage: type_variable::TypeVariableStorage<'tcx>,
 
     /// Map from const parameter variable to the kind of const it represents.
-    const_unification_table: ut::UnificationStorage<ty::ConstVid<'tcx>>,
+    const_unification_storage: ut::UnificationTableStorage<ty::ConstVid<'tcx>>,
 
     /// Map from integral variable to the kind of integer it represents.
-    int_unification_table: ut::UnificationStorage<ty::IntVid>,
+    int_unification_storage: ut::UnificationTableStorage<ty::IntVid>,
 
     /// Map from floating variable to the kind of float it represents.
-    float_unification_table: ut::UnificationStorage<ty::FloatVid>,
+    float_unification_storage: ut::UnificationTableStorage<ty::FloatVid>,
 
     /// Tracks the set of region variables and the constraints between them.
     /// This is initially `Some(_)` but when
@@ -196,41 +200,59 @@ pub struct InferCtxtInner<'tcx> {
     /// for each body-id in this map, which will process the
     /// obligations within. This is expected to be done 'late enough'
     /// that all type inference variables have been bound and so forth.
-    pub region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>,
+    region_obligations: Vec<(hir::HirId, RegionObligation<'tcx>)>,
+
+    undo_log: InferCtxtUndoLogs<'tcx>,
 }
 
 impl<'tcx> InferCtxtInner<'tcx> {
     fn new() -> InferCtxtInner<'tcx> {
         InferCtxtInner {
             projection_cache: Default::default(),
-            type_variables: type_variable::TypeVariableStorage::new(),
-            undo_log: Logs::default(),
-            const_unification_table: ut::UnificationStorage::new(),
-            int_unification_table: ut::UnificationStorage::new(),
-            float_unification_table: ut::UnificationStorage::new(),
+            type_variable_storage: type_variable::TypeVariableStorage::new(),
+            undo_log: InferCtxtUndoLogs::default(),
+            const_unification_storage: ut::UnificationTableStorage::new(),
+            int_unification_storage: ut::UnificationTableStorage::new(),
+            float_unification_storage: ut::UnificationTableStorage::new(),
             region_constraints: Some(RegionConstraintStorage::new()),
             region_obligations: vec![],
         }
     }
 
-    fn type_variables(&mut self) -> type_variable::TypeVariableTable<'tcx, '_> {
-        self.type_variables.with_log(&mut self.undo_log)
+    pub fn region_obligations(&self) -> &[(hir::HirId, RegionObligation<'tcx>)] {
+        &self.region_obligations
+    }
+
+    pub fn projection_cache(&mut self) -> traits::ProjectionCache<'_, 'tcx> {
+        self.projection_cache.with_log(&mut self.undo_log)
+    }
+
+    fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'tcx> {
+        self.type_variable_storage.with_log(&mut self.undo_log)
     }
 
     fn int_unification_table(
         &mut self,
     ) -> ut::UnificationTable<
-        ut::InPlace<ty::IntVid, &mut ut::UnificationStorage<ty::IntVid>, &mut Logs<'tcx>>,
+        ut::InPlace<
+            ty::IntVid,
+            &mut ut::UnificationStorage<ty::IntVid>,
+            &mut InferCtxtUndoLogs<'tcx>,
+        >,
     > {
-        ut::UnificationTable::with_log(&mut self.int_unification_table, &mut self.undo_log)
+        self.int_unification_storage.with_log(&mut self.undo_log)
     }
 
     fn float_unification_table(
         &mut self,
     ) -> ut::UnificationTable<
-        ut::InPlace<ty::FloatVid, &mut ut::UnificationStorage<ty::FloatVid>, &mut Logs<'tcx>>,
+        ut::InPlace<
+            ty::FloatVid,
+            &mut ut::UnificationStorage<ty::FloatVid>,
+            &mut InferCtxtUndoLogs<'tcx>,
+        >,
     > {
-        ut::UnificationTable::with_log(&mut self.float_unification_table, &mut self.undo_log)
+        self.float_unification_storage.with_log(&mut self.undo_log)
     }
 
     fn const_unification_table(
@@ -239,10 +261,10 @@ fn const_unification_table(
         ut::InPlace<
             ty::ConstVid<'tcx>,
             &mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
-            &mut Logs<'tcx>,
+            &mut InferCtxtUndoLogs<'tcx>,
         >,
     > {
-        ut::UnificationTable::with_log(&mut self.const_unification_table, &mut self.undo_log)
+        self.const_unification_storage.with_log(&mut self.undo_log)
     }
 
     pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'tcx, '_> {
@@ -253,202 +275,6 @@ pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'tcx, '
     }
 }
 
-pub struct Snapshot<'tcx> {
-    undo_len: usize,
-    _marker: PhantomData<&'tcx ()>,
-}
-
-pub(crate) enum UndoLog<'tcx> {
-    TypeVariables(type_variable::UndoLog<'tcx>),
-    ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
-    IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
-    FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
-    RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
-    RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
-}
-
-impl<'tcx> From<region_constraints::UndoLog<'tcx>> for UndoLog<'tcx> {
-    fn from(l: region_constraints::UndoLog<'tcx>) -> Self {
-        UndoLog::RegionConstraintCollector(l)
-    }
-}
-
-impl<'tcx> From<sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
-    fn from(l: sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>) -> Self {
-        UndoLog::TypeVariables(type_variable::UndoLog::EqRelation(l))
-    }
-}
-
-impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::TyVid>>> for UndoLog<'tcx> {
-    fn from(l: sv::UndoLog<ut::Delegate<ty::TyVid>>) -> Self {
-        UndoLog::TypeVariables(type_variable::UndoLog::SubRelation(l))
-    }
-}
-
-impl<'tcx> From<sv::UndoLog<type_variable::Delegate>> for UndoLog<'tcx> {
-    fn from(l: sv::UndoLog<type_variable::Delegate>) -> Self {
-        UndoLog::TypeVariables(type_variable::UndoLog::Values(l))
-    }
-}
-
-impl<'tcx> From<type_variable::Instantiate> for UndoLog<'tcx> {
-    fn from(l: type_variable::Instantiate) -> Self {
-        UndoLog::TypeVariables(type_variable::UndoLog::from(l))
-    }
-}
-
-impl From<type_variable::UndoLog<'tcx>> for UndoLog<'tcx> {
-    fn from(t: type_variable::UndoLog<'tcx>) -> Self {
-        Self::TypeVariables(t)
-    }
-}
-
-impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>> for UndoLog<'tcx> {
-    fn from(l: sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>) -> Self {
-        Self::ConstUnificationTable(l)
-    }
-}
-
-impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::IntVid>>> for UndoLog<'tcx> {
-    fn from(l: sv::UndoLog<ut::Delegate<ty::IntVid>>) -> Self {
-        Self::IntUnificationTable(l)
-    }
-}
-
-impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::FloatVid>>> for UndoLog<'tcx> {
-    fn from(l: sv::UndoLog<ut::Delegate<ty::FloatVid>>) -> Self {
-        Self::FloatUnificationTable(l)
-    }
-}
-
-impl<'tcx> From<sv::UndoLog<ut::Delegate<ty::RegionVid>>> for UndoLog<'tcx> {
-    fn from(l: sv::UndoLog<ut::Delegate<ty::RegionVid>>) -> Self {
-        Self::RegionUnificationTable(l)
-    }
-}
-
-pub(crate) type UnificationTable<'a, 'tcx, T> =
-    ut::UnificationTable<ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut Logs<'tcx>>>;
-
-struct RollbackView<'tcx, 'a> {
-    type_variables: type_variable::RollbackView<'tcx, 'a>,
-    const_unification_table: &'a mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
-    int_unification_table: &'a mut ut::UnificationStorage<ty::IntVid>,
-    float_unification_table: &'a mut ut::UnificationStorage<ty::FloatVid>,
-    region_constraints: &'a mut RegionConstraintStorage<'tcx>,
-}
-
-impl<'tcx> Rollback<UndoLog<'tcx>> for RollbackView<'tcx, '_> {
-    fn reverse(&mut self, undo: UndoLog<'tcx>) {
-        match undo {
-            UndoLog::TypeVariables(undo) => self.type_variables.reverse(undo),
-            UndoLog::ConstUnificationTable(undo) => self.const_unification_table.reverse(undo),
-            UndoLog::IntUnificationTable(undo) => self.int_unification_table.reverse(undo),
-            UndoLog::FloatUnificationTable(undo) => self.float_unification_table.reverse(undo),
-            UndoLog::RegionConstraintCollector(undo) => self.region_constraints.reverse(undo),
-            UndoLog::RegionUnificationTable(undo) => {
-                self.region_constraints.unification_table.reverse(undo)
-            }
-        }
-    }
-}
-
-pub(crate) struct Logs<'tcx> {
-    logs: Vec<UndoLog<'tcx>>,
-    num_open_snapshots: usize,
-}
-
-impl Default for Logs<'_> {
-    fn default() -> Self {
-        Self { logs: Default::default(), num_open_snapshots: Default::default() }
-    }
-}
-
-impl<'tcx, T> UndoLogs<T> for Logs<'tcx>
-where
-    UndoLog<'tcx>: From<T>,
-{
-    fn num_open_snapshots(&self) -> usize {
-        self.num_open_snapshots
-    }
-    fn push(&mut self, undo: T) {
-        if self.in_snapshot() {
-            self.logs.push(undo.into())
-        }
-    }
-    fn extend<J>(&mut self, undos: J)
-    where
-        Self: Sized,
-        J: IntoIterator<Item = T>,
-    {
-        if self.in_snapshot() {
-            self.logs.extend(undos.into_iter().map(UndoLog::from))
-        }
-    }
-}
-
-impl<'tcx> Snapshots<UndoLog<'tcx>> for Logs<'tcx> {
-    type Snapshot = Snapshot<'tcx>;
-    fn actions_since_snapshot(&self, snapshot: &Self::Snapshot) -> &[UndoLog<'tcx>] {
-        &self.logs[snapshot.undo_len..]
-    }
-
-    fn start_snapshot(&mut self) -> Self::Snapshot {
-        unreachable!()
-    }
-
-    fn rollback_to(&mut self, values: &mut impl Rollback<UndoLog<'tcx>>, snapshot: Self::Snapshot) {
-        debug!("rollback_to({})", snapshot.undo_len);
-        self.assert_open_snapshot(&snapshot);
-
-        while self.logs.len() > snapshot.undo_len {
-            values.reverse(self.logs.pop().unwrap());
-        }
-
-        if self.num_open_snapshots == 1 {
-            // The root snapshot. It's safe to clear the undo log because
-            // there's no snapshot further out that we might need to roll back
-            // to.
-            assert!(snapshot.undo_len == 0);
-            self.logs.clear();
-        }
-
-        self.num_open_snapshots -= 1;
-    }
-
-    fn commit(&mut self, snapshot: Self::Snapshot) {
-        debug!("commit({})", snapshot.undo_len);
-
-        if self.num_open_snapshots == 1 {
-            // The root snapshot. It's safe to clear the undo log because
-            // there's no snapshot further out that we might need to roll back
-            // to.
-            assert!(snapshot.undo_len == 0);
-            self.logs.clear();
-        }
-
-        self.num_open_snapshots -= 1;
-    }
-}
-
-impl<'tcx> Logs<'tcx> {
-    pub(crate) fn region_constraints(
-        &self,
-        after: usize,
-    ) -> impl Iterator<Item = &'_ region_constraints::UndoLog<'tcx>> + Clone {
-        self.logs[after..].iter().filter_map(|log| match log {
-            UndoLog::RegionConstraintCollector(log) => Some(log),
-            _ => None,
-        })
-    }
-
-    fn assert_open_snapshot(&self, snapshot: &Snapshot<'tcx>) {
-        // Failures here may indicate a failure to follow a stack discipline.
-        assert!(self.logs.len() >= snapshot.undo_len);
-        assert!(self.num_open_snapshots > 0);
-    }
-}
-
 pub struct InferCtxt<'a, 'tcx> {
     pub tcx: TyCtxt<'tcx>,
 
@@ -879,19 +705,21 @@ pub fn into_obligations(self) -> PredicateObligations<'tcx> {
     }
 }
 
+#[must_use = "once you start a snapshot, you should always consume it"]
+pub struct FullSnapshot<'a, 'tcx> {
+    snapshot: CombinedSnapshot<'a, 'tcx>,
+    region_constraints_snapshot: RegionSnapshot,
+    type_snapshot: type_variable::Snapshot<'tcx>,
+    const_var_len: usize,
+    int_var_len: usize,
+    float_var_len: usize,
+}
+
 #[must_use = "once you start a snapshot, you should always consume it"]
 pub struct CombinedSnapshot<'a, 'tcx> {
-    projection_cache_snapshot: traits::ProjectionCacheSnapshot,
     undo_snapshot: Snapshot<'tcx>,
-    type_snapshot: type_variable::Snapshot<'tcx>,
-    const_snapshot: usize,
-    int_snapshot: usize,
-    float_snapshot: usize,
-    region_constraints_snapshot: RegionSnapshot,
-    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>>>,
 }
 
@@ -1002,6 +830,19 @@ pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R
         result
     }
 
+    fn start_full_snapshot(&self) -> FullSnapshot<'a, 'tcx> {
+        let snapshot = self.start_snapshot();
+        let mut inner = self.inner.borrow_mut();
+        FullSnapshot {
+            snapshot,
+            type_snapshot: inner.type_variables().snapshot(),
+            const_var_len: inner.const_unification_table().len(),
+            int_var_len: inner.int_unification_table().len(),
+            float_var_len: inner.float_unification_table().len(),
+            region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
+        }
+    }
+
     fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> {
         debug!("start_snapshot()");
 
@@ -1009,20 +850,10 @@ fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> {
 
         let mut inner = self.inner.borrow_mut();
 
-        inner.undo_log.num_open_snapshots += 1;
-        let undo_snapshot = Snapshot { undo_len: inner.undo_log.logs.len(), _marker: PhantomData };
         CombinedSnapshot {
-            projection_cache_snapshot: inner.projection_cache.snapshot(),
-            undo_snapshot,
-            type_snapshot: inner.type_variables().snapshot(),
-            const_snapshot: inner.const_unification_table().len(),
-            int_snapshot: inner.int_unification_table().len(),
-            float_snapshot: inner.float_unification_table().len(),
-            region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
-            region_obligations_snapshot: inner.region_obligations.len(),
+            undo_snapshot: inner.undo_log.start_snapshot(),
             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()),
@@ -1031,72 +862,23 @@ fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> {
 
     fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) {
         debug!("rollback_to(cause={})", cause);
-        let CombinedSnapshot {
-            projection_cache_snapshot,
-            undo_snapshot,
-            type_snapshot: _,
-            const_snapshot: _,
-            int_snapshot: _,
-            float_snapshot: _,
-            region_constraints_snapshot: _,
-            region_obligations_snapshot,
-            universe,
-            was_in_snapshot,
-            was_skip_leak_check,
-            _in_progress_tables,
-        } = snapshot;
+        let CombinedSnapshot { undo_snapshot, universe, was_in_snapshot, _in_progress_tables } =
+            snapshot;
 
         self.in_snapshot.set(was_in_snapshot);
         self.universe.set(universe);
-        self.skip_leak_check.set(was_skip_leak_check);
 
-        let mut inner = self.inner.borrow_mut();
-        let inner = &mut *inner;
-        let InferCtxtInner {
-            type_variables,
-            const_unification_table,
-            int_unification_table,
-            float_unification_table,
-            region_constraints,
-            ..
-        } = inner;
-        inner.undo_log.rollback_to(
-            &mut RollbackView {
-                type_variables: type_variable::RollbackView::from(type_variables),
-                const_unification_table,
-                int_unification_table,
-                float_unification_table,
-                region_constraints: region_constraints.as_mut().unwrap(),
-            },
-            undo_snapshot,
-        );
-        inner.projection_cache.rollback_to(projection_cache_snapshot);
-        inner.region_obligations.truncate(region_obligations_snapshot);
+        self.inner.borrow_mut().rollback_to(undo_snapshot);
     }
 
     fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
         debug!("commit_from()");
-        let CombinedSnapshot {
-            projection_cache_snapshot,
-            undo_snapshot,
-            type_snapshot: _,
-            const_snapshot: _,
-            int_snapshot: _,
-            float_snapshot: _,
-            region_constraints_snapshot: _,
-            region_obligations_snapshot: _,
-            universe: _,
-            was_in_snapshot,
-            was_skip_leak_check,
-            _in_progress_tables,
-        } = snapshot;
+        let CombinedSnapshot { undo_snapshot, universe: _, was_in_snapshot, _in_progress_tables } =
+            snapshot;
 
         self.in_snapshot.set(was_in_snapshot);
-        self.skip_leak_check.set(was_skip_leak_check);
 
-        let mut inner = self.inner.borrow_mut();
-        inner.undo_log.commit(undo_snapshot);
-        inner.projection_cache.commit(projection_cache_snapshot);
+        self.inner.borrow_mut().commit(undo_snapshot);
     }
 
     /// Executes `f` and commit the bindings.
@@ -1143,6 +925,17 @@ pub fn probe<R, F>(&self, f: F) -> R
         r
     }
 
+    pub fn probe_full<R, F>(&self, f: F) -> R
+    where
+        F: FnOnce(&FullSnapshot<'a, 'tcx>) -> R,
+    {
+        debug!("probe()");
+        let snapshot = self.start_full_snapshot();
+        let r = f(&snapshot);
+        self.rollback_to("probe", snapshot.snapshot);
+        r
+    }
+
     /// If `should_skip` is true, then execute `f` then unroll any bindings it creates.
     pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R
     where
@@ -1150,10 +943,13 @@ pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R
     {
         debug!("probe()");
         let snapshot = self.start_snapshot();
-        let skip_leak_check = should_skip || self.skip_leak_check.get();
-        self.skip_leak_check.set(skip_leak_check);
+        let was_skip_leak_check = self.skip_leak_check.get();
+        if should_skip {
+            self.skip_leak_check.set(true);
+        }
         let r = f(&snapshot);
         self.rollback_to("probe", snapshot);
+        self.skip_leak_check.set(was_skip_leak_check);
         r
     }
 
@@ -1489,19 +1285,21 @@ pub fn resolve_regions_and_report_errors(
         outlives_env: &OutlivesEnvironment<'tcx>,
         mode: RegionckMode,
     ) {
-        assert!(
-            self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(),
-            "region_obligations not empty: {:#?}",
-            self.inner.borrow().region_obligations
-        );
-        let (var_infos, data) = self
-            .inner
-            .borrow_mut()
-            .region_constraints
-            .take()
-            .expect("regions already resolved")
-            .with_log(&mut inner.undo_log)
-            .into_infos_and_data();
+        let (var_infos, data) = {
+            let mut inner = self.inner.borrow_mut();
+            let inner = &mut *inner;
+            assert!(
+                self.is_tainted_by_errors() || inner.region_obligations.is_empty(),
+                "region_obligations not empty: {:#?}",
+                inner.region_obligations
+            );
+            inner
+                .region_constraints
+                .take()
+                .expect("regions already resolved")
+                .with_log(&mut inner.undo_log)
+                .into_infos_and_data()
+        };
 
         let region_rels = &RegionRelations::new(
             self.tcx,
@@ -1769,7 +1567,7 @@ pub fn closure_kind(&self, closure_substs: SubstsRef<'tcx>) -> Option<ty::Closur
     pub fn clear_caches(&self) {
         self.selection_cache.clear();
         self.evaluation_cache.clear();
-        self.inner.borrow_mut().projection_cache.clear();
+        self.inner.borrow_mut().projection_cache().clear();
     }
 
     fn universe(&self) -> ty::UniverseIndex {
@@ -1867,13 +1665,14 @@ fn shallow_resolve_ty(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
     /// having to resort to storing full `GenericArg`s in `stalled_on`.
     #[inline(always)]
     pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar<'tcx>) -> bool {
+        let mut inner = self.inner.borrow_mut();
         match infer_var {
             TyOrConstInferVar::Ty(v) => {
                 use self::type_variable::TypeVariableValue;
 
                 // If `inlined_probe` returns a `Known` value, it never equals
                 // `ty::Infer(ty::TyVar(v))`.
-                match self.inner.borrow_mut().type_variables().inlined_probe(v) {
+                match inner.type_variables().inlined_probe(v) {
                     TypeVariableValue::Unknown { .. } => false,
                     TypeVariableValue::Known { .. } => true,
                 }
@@ -1883,7 +1682,7 @@ pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar<'tcx>)
                 // If `inlined_probe_value` returns a value it's always a
                 // `ty::Int(_)` or `ty::UInt(_)`, which never matches a
                 // `ty::Infer(_)`.
-                self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_some()
+                inner.int_unification_table().inlined_probe_value(v).is_some()
             }
 
             TyOrConstInferVar::TyFloat(v) => {
@@ -1891,7 +1690,7 @@ pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar<'tcx>)
                 // `ty::Float(_)`, which never matches a `ty::Infer(_)`.
                 //
                 // Not `inlined_probe_value(v)` because this call site is colder.
-                self.inner.borrow_mut().float_unification_table().probe_value(v).is_some()
+                inner.float_unification_table().probe_value(v).is_some()
             }
 
             TyOrConstInferVar::Const(v) => {
@@ -1899,7 +1698,7 @@ pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar<'tcx>)
                 // `ty::ConstKind::Infer(ty::InferConst::Var(v))`.
                 //
                 // Not `inlined_probe_value(v)` because this call site is colder.
-                match self.inner.borrow_mut().const_unification_table.probe_value(v).val {
+                match inner.const_unification_table().probe_value(v).val {
                     ConstVariableValue::Unknown { .. } => false,
                     ConstVariableValue::Known { .. } => true,
                 }