when pop skol, also remove from proj cache

This commit is contained in:
Niko Matsakis 2016-10-18 21:32:31 -04:00
parent da5b6467c3
commit 974817d493
3 changed files with 51 additions and 17 deletions

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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>