]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_infer/traits/project.rs
Fix review comments
[rust.git] / src / librustc_infer / traits / project.rs
index 48375a9ddf418eba274b1d6b1339e1615018b43a..f0d21a7d022daf80dcb64f002a3e64ca2d804b13 100644 (file)
@@ -2,12 +2,19 @@
 
 use super::PredicateObligation;
 
-use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
-use rustc_middle::ty::fold::TypeFoldable;
+use crate::infer::InferCtxtUndoLogs;
+
+use rustc_data_structures::{
+    snapshot_map::{self, SnapshotMapRef, SnapshotMapStorage},
+    undo_log::Rollback,
+};
 use rustc_middle::ty::{self, Ty};
 
 pub use rustc_middle::traits::Reveal;
 
+pub(crate) type UndoLog<'tcx> =
+    snapshot_map::UndoLog<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>;
+
 #[derive(Clone)]
 pub struct MismatchedProjectionTypes<'tcx> {
     pub err: ty::error::TypeError<'tcx>,
@@ -58,9 +65,14 @@ pub fn with<U>(self, value: U) -> Normalized<'tcx, U> {
 //
 // FIXME: we probably also want some sort of cross-infcx cache here to
 // reduce the amount of duplication. Let's see what we get with the Chalk reforms.
+pub struct ProjectionCache<'a, 'tcx> {
+    map: &'a mut SnapshotMapStorage<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>,
+    undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
+}
+
 #[derive(Default)]
-pub struct ProjectionCache<'tcx> {
-    map: SnapshotMap<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>,
+pub struct ProjectionCacheStorage<'tcx> {
+    map: SnapshotMapStorage<ProjectionCacheKey<'tcx>, ProjectionCacheEntry<'tcx>>,
 }
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -82,30 +94,29 @@ pub enum ProjectionCacheEntry<'tcx> {
     NormalizedTy(NormalizedTy<'tcx>),
 }
 
-// N.B., intentionally not Clone
-pub struct ProjectionCacheSnapshot {
-    snapshot: Snapshot,
-}
-
-impl<'tcx> ProjectionCache<'tcx> {
-    pub fn clear(&mut self) {
-        self.map.clear();
-    }
-
-    pub fn snapshot(&mut self) -> ProjectionCacheSnapshot {
-        ProjectionCacheSnapshot { snapshot: self.map.snapshot() }
-    }
-
-    pub fn rollback_to(&mut self, snapshot: ProjectionCacheSnapshot) {
-        self.map.rollback_to(snapshot.snapshot);
+impl<'tcx> ProjectionCacheStorage<'tcx> {
+    pub(crate) fn with_log<'a>(
+        &'a mut self,
+        undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
+    ) -> ProjectionCache<'a, 'tcx> {
+        ProjectionCache { map: &mut self.map, undo_log }
     }
+}
 
-    pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) {
-        self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_placeholders());
+impl<'tcx> ProjectionCache<'_, 'tcx> {
+    fn map(
+        &mut self,
+    ) -> SnapshotMapRef<
+        '_,
+        ProjectionCacheKey<'tcx>,
+        ProjectionCacheEntry<'tcx>,
+        InferCtxtUndoLogs<'tcx>,
+    > {
+        self.map.with_log(self.undo_log)
     }
 
-    pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) {
-        self.map.commit(snapshot.snapshot);
+    pub fn clear(&mut self) {
+        self.map().clear();
     }
 
     /// Try to start normalize `key`; returns an error if
@@ -115,11 +126,12 @@ pub fn try_start(
         &mut self,
         key: ProjectionCacheKey<'tcx>,
     ) -> Result<(), ProjectionCacheEntry<'tcx>> {
-        if let Some(entry) = self.map.get(&key) {
+        let mut map = self.map();
+        if let Some(entry) = map.get(&key) {
             return Err(entry.clone());
         }
 
-        self.map.insert(key, ProjectionCacheEntry::InProgress);
+        map.insert(key, ProjectionCacheEntry::InProgress);
         Ok(())
     }
 
@@ -129,7 +141,7 @@ pub fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'
             "ProjectionCacheEntry::insert_ty: adding cache entry: key={:?}, value={:?}",
             key, value
         );
-        let fresh_key = self.map.insert(key, ProjectionCacheEntry::NormalizedTy(value));
+        let fresh_key = self.map().insert(key, ProjectionCacheEntry::NormalizedTy(value));
         assert!(!fresh_key, "never started projecting `{:?}`", key);
     }
 
@@ -138,7 +150,8 @@ pub fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'
     /// snapshot - if the snapshot is rolled back, the obligations will be
     /// marked as incomplete again).
     pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>) {
-        let ty = match self.map.get(&key) {
+        let mut map = self.map();
+        let ty = match map.get(&key) {
             Some(&ProjectionCacheEntry::NormalizedTy(ref ty)) => {
                 debug!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
                 ty.value
@@ -151,7 +164,7 @@ pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>) {
             }
         };
 
-        self.map.insert(
+        map.insert(
             key,
             ProjectionCacheEntry::NormalizedTy(Normalized { value: ty, obligations: vec![] }),
         );
@@ -163,7 +176,7 @@ pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &Normal
         // We want to insert `ty` with no obligations. If the existing value
         // already has no obligations (as is common) we don't insert anything.
         if !ty.obligations.is_empty() {
-            self.map.insert(
+            self.map().insert(
                 key,
                 ProjectionCacheEntry::NormalizedTy(Normalized {
                     value: ty.value,
@@ -178,14 +191,20 @@ pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &Normal
     /// type information (in which case, the "fully resolved" key will
     /// be different).
     pub fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
-        let fresh = self.map.insert(key, ProjectionCacheEntry::Ambiguous);
+        let fresh = self.map().insert(key, ProjectionCacheEntry::Ambiguous);
         assert!(!fresh, "never started projecting `{:?}`", key);
     }
 
     /// Indicates that trying to normalize `key` resulted in
     /// error.
     pub fn error(&mut self, key: ProjectionCacheKey<'tcx>) {
-        let fresh = self.map.insert(key, ProjectionCacheEntry::Error);
+        let fresh = self.map().insert(key, ProjectionCacheEntry::Error);
         assert!(!fresh, "never started projecting `{:?}`", key);
     }
 }
+
+impl<'tcx> Rollback<UndoLog<'tcx>> for ProjectionCacheStorage<'tcx> {
+    fn reverse(&mut self, undo: UndoLog<'tcx>) {
+        self.map.reverse(undo);
+    }
+}