Skip to content

Commit c50fc6e

Browse files
author
Markus Westerlind
committed
Allow SnapshotMap to have a separate undo_log
1 parent caacdd2 commit c50fc6e

File tree

3 files changed

+62
-96
lines changed

3 files changed

+62
-96
lines changed
Lines changed: 58 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,127 @@
11
use crate::fx::FxHashMap;
2+
use crate::undo_log::{Rollback, Snapshots, UndoLogs, VecLog};
23
use std::hash::Hash;
3-
use std::mem;
4+
use std::marker::PhantomData;
45
use std::ops;
56

7+
pub use crate::undo_log::Snapshot;
8+
69
#[cfg(test)]
710
mod tests;
811

9-
pub struct SnapshotMap<K, V>
10-
where
11-
K: Clone + Eq,
12-
{
13-
map: FxHashMap<K, V>,
14-
undo_log: Vec<UndoLog<K, V>>,
15-
num_open_snapshots: usize,
12+
pub type SnapshotMapStorage<K, V> = SnapshotMap<K, V, FxHashMap<K, V>, ()>;
13+
14+
pub struct SnapshotMap<K, V, M = FxHashMap<K, V>, L = VecLog<UndoLog<K, V>>> {
15+
map: M,
16+
undo_log: L,
17+
_marker: PhantomData<(K, V)>,
1618
}
1719

1820
// HACK(eddyb) manual impl avoids `Default` bounds on `K` and `V`.
19-
impl<K, V> Default for SnapshotMap<K, V>
21+
impl<K, V, M, L> Default for SnapshotMap<K, V, M, L>
2022
where
21-
K: Hash + Clone + Eq,
23+
M: Default,
24+
L: Default,
2225
{
2326
fn default() -> Self {
24-
SnapshotMap { map: Default::default(), undo_log: Default::default(), num_open_snapshots: 0 }
27+
SnapshotMap { map: Default::default(), undo_log: Default::default(), _marker: PhantomData }
2528
}
2629
}
2730

28-
pub struct Snapshot {
29-
len: usize,
30-
}
31-
32-
enum UndoLog<K, V> {
31+
pub enum UndoLog<K, V> {
3332
Inserted(K),
3433
Overwrite(K, V),
3534
Purged,
3635
}
3736

38-
impl<K, V> SnapshotMap<K, V>
37+
impl<K, V, M, L> SnapshotMap<K, V, M, L> {
38+
pub fn with_log<L2>(&mut self, undo_log: L2) -> SnapshotMap<K, V, &mut M, L2> {
39+
SnapshotMap { map: &mut self.map, undo_log, _marker: PhantomData }
40+
}
41+
}
42+
43+
impl<K, V, M, L> SnapshotMap<K, V, M, L>
3944
where
4045
K: Hash + Clone + Eq,
46+
M: AsMut<FxHashMap<K, V>> + AsRef<FxHashMap<K, V>>,
47+
L: UndoLogs<UndoLog<K, V>>,
4148
{
4249
pub fn clear(&mut self) {
43-
self.map.clear();
50+
self.map.as_mut().clear();
4451
self.undo_log.clear();
45-
self.num_open_snapshots = 0;
46-
}
47-
48-
fn in_snapshot(&self) -> bool {
49-
self.num_open_snapshots > 0
5052
}
5153

5254
pub fn insert(&mut self, key: K, value: V) -> bool {
53-
match self.map.insert(key.clone(), value) {
55+
match self.map.as_mut().insert(key.clone(), value) {
5456
None => {
55-
if self.in_snapshot() {
56-
self.undo_log.push(UndoLog::Inserted(key));
57-
}
57+
self.undo_log.push(UndoLog::Inserted(key));
5858
true
5959
}
6060
Some(old_value) => {
61-
if self.in_snapshot() {
62-
self.undo_log.push(UndoLog::Overwrite(key, old_value));
63-
}
61+
self.undo_log.push(UndoLog::Overwrite(key, old_value));
6462
false
6563
}
6664
}
6765
}
6866

6967
pub fn remove(&mut self, key: K) -> bool {
70-
match self.map.remove(&key) {
68+
match self.map.as_mut().remove(&key) {
7169
Some(old_value) => {
72-
if self.in_snapshot() {
73-
self.undo_log.push(UndoLog::Overwrite(key, old_value));
74-
}
70+
self.undo_log.push(UndoLog::Overwrite(key, old_value));
7571
true
7672
}
7773
None => false,
7874
}
7975
}
8076

8177
pub fn get(&self, key: &K) -> Option<&V> {
82-
self.map.get(key)
78+
self.map.as_ref().get(key)
8379
}
80+
}
8481

82+
impl<K, V> SnapshotMap<K, V>
83+
where
84+
K: Hash + Clone + Eq,
85+
{
8586
pub fn snapshot(&mut self) -> Snapshot {
86-
let len = self.undo_log.len();
87-
self.num_open_snapshots += 1;
88-
Snapshot { len }
89-
}
90-
91-
fn assert_open_snapshot(&self, snapshot: &Snapshot) {
92-
assert!(self.undo_log.len() >= snapshot.len);
93-
assert!(self.num_open_snapshots > 0);
87+
self.undo_log.start_snapshot()
9488
}
9589

9690
pub fn commit(&mut self, snapshot: Snapshot) {
97-
self.assert_open_snapshot(&snapshot);
98-
if self.num_open_snapshots == 1 {
99-
// The root snapshot. It's safe to clear the undo log because
100-
// there's no snapshot further out that we might need to roll back
101-
// to.
102-
assert!(snapshot.len == 0);
103-
self.undo_log.clear();
104-
}
105-
106-
self.num_open_snapshots -= 1;
107-
}
108-
109-
pub fn partial_rollback<F>(&mut self, snapshot: &Snapshot, should_revert_key: &F)
110-
where
111-
F: Fn(&K) -> bool,
112-
{
113-
self.assert_open_snapshot(snapshot);
114-
for i in (snapshot.len..self.undo_log.len()).rev() {
115-
let reverse = match self.undo_log[i] {
116-
UndoLog::Purged => false,
117-
UndoLog::Inserted(ref k) => should_revert_key(k),
118-
UndoLog::Overwrite(ref k, _) => should_revert_key(k),
119-
};
120-
121-
if reverse {
122-
let entry = mem::replace(&mut self.undo_log[i], UndoLog::Purged);
123-
self.reverse(entry);
124-
}
125-
}
91+
self.undo_log.commit(snapshot)
12692
}
12793

12894
pub fn rollback_to(&mut self, snapshot: Snapshot) {
129-
self.assert_open_snapshot(&snapshot);
130-
while self.undo_log.len() > snapshot.len {
131-
let entry = self.undo_log.pop().unwrap();
132-
self.reverse(entry);
133-
}
95+
self.undo_log.rollback_to(&mut self.map, snapshot)
96+
}
97+
}
13498

135-
self.num_open_snapshots -= 1;
99+
impl<'k, K, V, M, L> ops::Index<&'k K> for SnapshotMap<K, V, M, L>
100+
where
101+
K: Hash + Clone + Eq,
102+
M: AsRef<FxHashMap<K, V>>,
103+
{
104+
type Output = V;
105+
fn index(&self, key: &'k K) -> &V {
106+
&self.map.as_ref()[key]
136107
}
108+
}
137109

138-
fn reverse(&mut self, entry: UndoLog<K, V>) {
139-
match entry {
110+
impl<K, V> Rollback<UndoLog<K, V>> for FxHashMap<K, V>
111+
where
112+
K: Eq + Hash,
113+
{
114+
fn reverse(&mut self, undo: UndoLog<K, V>) {
115+
match undo {
140116
UndoLog::Inserted(key) => {
141-
self.map.remove(&key);
117+
self.remove(&key);
142118
}
143119

144120
UndoLog::Overwrite(key, old_value) => {
145-
self.map.insert(key, old_value);
121+
self.insert(key, old_value);
146122
}
147123

148124
UndoLog::Purged => {}
149125
}
150126
}
151127
}
152-
153-
impl<'k, K, V> ops::Index<&'k K> for SnapshotMap<K, V>
154-
where
155-
K: Hash + Clone + Eq,
156-
{
157-
type Output = V;
158-
fn index(&self, key: &'k K) -> &V {
159-
&self.map[key]
160-
}
161-
}

src/librustc_infer/infer/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,10 @@ where
376376
self.logs.push(undo.into())
377377
}
378378
}
379+
fn clear(&mut self) {
380+
self.logs.clear();
381+
self.num_open_snapshots = 0;
382+
}
379383
fn extend<J>(&mut self, undos: J)
380384
where
381385
Self: Sized,

src/librustc_infer/traits/project.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ impl<'tcx> ProjectionCache<'tcx> {
100100
self.map.rollback_to(snapshot.snapshot);
101101
}
102102

103-
pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) {
104-
self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_placeholders());
105-
}
106-
107103
pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) {
108104
self.map.commit(snapshot.snapshot);
109105
}

0 commit comments

Comments
 (0)