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); debug!("pop_skolemized({:?})", skol_map);
let skol_regions: FnvHashSet<_> = skol_map.values().cloned().collect(); let skol_regions: FnvHashSet<_> = skol_map.values().cloned().collect();
self.region_vars.pop_skolemized(&skol_regions, &snapshot.region_vars_snapshot); 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); infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot);
let skol_obligation = obligation.with(skol_predicate); 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) => { Ok(result) => {
let span = obligation.cause.span; let span = obligation.cause.span;
match infcx.leak_check(false, span, &skol_map, snapshot) { 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) => {
Err(e) Err(e)
} }
} };
r
}) })
} }
@ -1396,6 +1398,10 @@ impl<'tcx> ProjectionCache<'tcx> {
self.map.rollback_to(snapshot.snapshot); 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) { pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) {
self.map.commit(snapshot.snapshot); self.map.commit(snapshot.snapshot);
} }

View File

@ -11,6 +11,7 @@
use fnv::FnvHashMap; use fnv::FnvHashMap;
use std::hash::Hash; use std::hash::Hash;
use std::ops; use std::ops;
use std::mem;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
@ -31,6 +32,7 @@ enum UndoLog<K, V> {
CommittedSnapshot, CommittedSnapshot,
Inserted(K), Inserted(K),
Overwrite(K, V), Overwrite(K, V),
Noop,
} }
impl<K, V> SnapshotMap<K, V> 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) { pub fn rollback_to(&mut self, snapshot: Snapshot) {
self.assert_open_snapshot(&snapshot); self.assert_open_snapshot(&snapshot);
while self.undo_log.len() > snapshot.len + 1 { while self.undo_log.len() > snapshot.len + 1 {
match self.undo_log.pop().unwrap() { let entry = self.undo_log.pop().unwrap();
UndoLog::OpenSnapshot => { self.reverse(entry);
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 v = self.undo_log.pop().unwrap(); let v = self.undo_log.pop().unwrap();
@ -127,6 +134,26 @@ impl<K, V> SnapshotMap<K, V>
}); });
assert!(self.undo_log.len() == snapshot.len); 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> impl<'k, K, V> ops::Index<&'k K> for SnapshotMap<K, V>