about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-10-18 21:32:31 -0400
committerNiko Matsakis <niko@alum.mit.edu>2016-10-21 11:13:34 -0400
commit974817d4932fd447f724c4527360a258952ffd48 (patch)
treeabf55340848ec3df65ca2773cbdd155dfc028a01
parentda5b6467c33f7f86b4964b08b37726f7611a8f0c (diff)
when pop skol, also remove from proj cache
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs1
-rw-r--r--src/librustc/traits/project.rs10
-rw-r--r--src/librustc_data_structures/snapshot_map/mod.rs57
3 files changed, 51 insertions, 17 deletions
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index c1d9240ba06..069fb3e7967 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -839,5 +839,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         debug!("pop_skolemized({:?})", skol_map);
         let skol_regions: FnvHashSet<_> = skol_map.values().cloned().collect();
         self.region_vars.pop_skolemized(&skol_regions, &snapshot.region_vars_snapshot);
+        self.projection_cache.borrow_mut().partial_rollback(&snapshot.projection_cache_snapshot);
     }
 }
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 27554c0d2a4..71196306121 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -167,7 +167,7 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>(
             infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot);
 
         let skol_obligation = obligation.with(skol_predicate);
-        match project_and_unify_type(selcx, &skol_obligation) {
+        let r = match project_and_unify_type(selcx, &skol_obligation) {
             Ok(result) => {
                 let span = obligation.cause.span;
                 match infcx.leak_check(false, span, &skol_map, snapshot) {
@@ -178,7 +178,9 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>(
             Err(e) => {
                 Err(e)
             }
-        }
+        };
+
+        r
     })
 }
 
@@ -1396,6 +1398,10 @@ impl<'tcx> ProjectionCache<'tcx> {
         self.map.rollback_to(snapshot.snapshot);
     }
 
+    pub fn partial_rollback(&mut self, snapshot: &ProjectionCacheSnapshot) {
+        self.map.partial_rollback(&snapshot.snapshot);
+    }
+
     pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) {
         self.map.commit(snapshot.snapshot);
     }
diff --git a/src/librustc_data_structures/snapshot_map/mod.rs b/src/librustc_data_structures/snapshot_map/mod.rs
index 0306066d6e7..23a67b3bd93 100644
--- a/src/librustc_data_structures/snapshot_map/mod.rs
+++ b/src/librustc_data_structures/snapshot_map/mod.rs
@@ -11,6 +11,7 @@
 use fnv::FnvHashMap;
 use std::hash::Hash;
 use std::ops;
+use std::mem;
 
 #[cfg(test)]
 mod test;
@@ -31,6 +32,7 @@ enum UndoLog<K, V> {
     CommittedSnapshot,
     Inserted(K),
     Overwrite(K, V),
+    Noop,
 }
 
 impl<K, V> SnapshotMap<K, V>
@@ -100,24 +102,29 @@ impl<K, V> SnapshotMap<K, V>
         }
     }
 
+    pub fn partial_rollback(&mut self, snapshot: &Snapshot) {
+        self.assert_open_snapshot(snapshot);
+        for i in (snapshot.len + 1..self.undo_log.len()).rev() {
+            let reverse = match self.undo_log[i] {
+                UndoLog::OpenSnapshot => false,
+                UndoLog::CommittedSnapshot => false,
+                UndoLog::Noop => false,
+                UndoLog::Inserted(..) => true,
+                UndoLog::Overwrite(..) => true,
+            };
+
+            if reverse {
+                let entry = mem::replace(&mut self.undo_log[i], UndoLog::Noop);
+                self.reverse(entry);
+            }
+        }
+    }
+
     pub fn rollback_to(&mut self, snapshot: Snapshot) {
         self.assert_open_snapshot(&snapshot);
         while self.undo_log.len() > snapshot.len + 1 {
-            match self.undo_log.pop().unwrap() {
-                UndoLog::OpenSnapshot => {
-                    panic!("cannot rollback an uncommitted snapshot");
-                }
-
-                UndoLog::CommittedSnapshot => {}
-
-                UndoLog::Inserted(key) => {
-                    self.map.remove(&key);
-                }
-
-                UndoLog::Overwrite(key, old_value) => {
-                    self.map.insert(key, old_value);
-                }
-            }
+            let entry = self.undo_log.pop().unwrap();
+            self.reverse(entry);
         }
 
         let v = self.undo_log.pop().unwrap();
@@ -127,6 +134,26 @@ impl<K, V> SnapshotMap<K, V>
         });
         assert!(self.undo_log.len() == snapshot.len);
     }
+
+    fn reverse(&mut self, entry: UndoLog<K, V>) {
+        match entry {
+            UndoLog::OpenSnapshot => {
+                panic!("cannot rollback an uncommitted snapshot");
+            }
+
+            UndoLog::CommittedSnapshot => {}
+
+            UndoLog::Inserted(key) => {
+                self.map.remove(&key);
+            }
+
+            UndoLog::Overwrite(key, old_value) => {
+                self.map.insert(key, old_value);
+            }
+
+            UndoLog::Noop => {}
+        }
+    }
 }
 
 impl<'k, K, V> ops::Index<&'k K> for SnapshotMap<K, V>