Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e9bca7a

Browse files
committedNov 25, 2018
Auto merge of #55906 - nnethercote:rm-OpenSnapshot-CommittedSnapshot, r=nikomatsakis
Clean up and streamline snapshot data structures These commits clean up the snapshot structures a bit, so they are more consistent with each other and with the `ena` crate. They also remove the `OpenSnapshot` and `CommittedSnapshot` entries in the undo log, just like I did for the `ena` crate in rust-lang/ena#14. This PR in combination with that `ena` PR reduces instruction counts by up to 6% on benchmarks. r? @nikomatsakis. Note that this isn't quite ready for landing, because the `ena` dependency in the first commit needs to be updated once rust-lang/ena#14 lands. But otherwise it should be good.
2 parents abe19a7 + 94967ae commit e9bca7a

File tree

9 files changed

+96
-118
lines changed

9 files changed

+96
-118
lines changed
 

‎Cargo.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ dependencies = [
661661

662662
[[package]]
663663
name = "ena"
664-
version = "0.10.1"
664+
version = "0.11.0"
665665
source = "registry+https://github.com/rust-lang/crates.io-index"
666666
dependencies = [
667667
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2230,7 +2230,7 @@ name = "rustc_data_structures"
22302230
version = "0.0.0"
22312231
dependencies = [
22322232
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
2233-
"ena 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
2233+
"ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
22342234
"graphviz 0.0.0",
22352235
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
22362236
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3295,7 +3295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
32953295
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
32963296
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
32973297
"checksum elasticlunr-rs 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4837d77a1e157489a3933b743fd774ae75074e0e390b2b7f071530048a0d87ee"
3298-
"checksum ena 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25b4e5febb25f08c49f1b07dc33a182729a6b21edfb562b5aef95f78e0dbe5bb"
3298+
"checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00"
32993299
"checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621"
33003300
"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257"
33013301
"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"

‎src/librustc/infer/higher_ranked/mod.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,11 +554,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
554554
) {
555555
debug!("pop_placeholders({:?})", placeholder_map);
556556
let placeholder_regions: FxHashSet<_> = placeholder_map.values().cloned().collect();
557-
self.borrow_region_constraints()
558-
.pop_placeholders(
559-
&placeholder_regions,
560-
&snapshot.region_constraints_snapshot,
561-
);
557+
self.borrow_region_constraints().pop_placeholders(&placeholder_regions);
562558
self.universe.set(snapshot.universe);
563559
if !placeholder_map.is_empty() {
564560
self.projection_cache.borrow_mut().rollback_placeholder(

‎src/librustc/infer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
790790

791791
self.projection_cache
792792
.borrow_mut()
793-
.commit(&projection_cache_snapshot);
793+
.commit(projection_cache_snapshot);
794794
self.type_variables.borrow_mut().commit(type_snapshot);
795795
self.int_unification_table.borrow_mut().commit(int_snapshot);
796796
self.float_unification_table

‎src/librustc/infer/region_constraints/mod.rs

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! See README.md
1212
1313
use self::CombineMapType::*;
14-
use self::UndoLogEntry::*;
14+
use self::UndoLog::*;
1515

1616
use super::unify_key;
1717
use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
@@ -52,14 +52,17 @@ pub struct RegionConstraintCollector<'tcx> {
5252

5353
/// The undo log records actions that might later be undone.
5454
///
55-
/// Note: when the undo_log is empty, we are not actively
55+
/// Note: `num_open_snapshots` is used to track if we are actively
5656
/// snapshotting. When the `start_snapshot()` method is called, we
57-
/// push an OpenSnapshot entry onto the list to indicate that we
58-
/// are now actively snapshotting. The reason for this is that
59-
/// otherwise we end up adding entries for things like the lower
60-
/// bound on a variable and so forth, which can never be rolled
61-
/// back.
62-
undo_log: Vec<UndoLogEntry<'tcx>>,
57+
/// increment `num_open_snapshots` to indicate that we are now actively
58+
/// snapshotting. The reason for this is that otherwise we end up adding
59+
/// entries for things like the lower bound on a variable and so forth,
60+
/// which can never be rolled back.
61+
undo_log: Vec<UndoLog<'tcx>>,
62+
63+
/// The number of open snapshots, i.e. those that haven't been committed or
64+
/// rolled back.
65+
num_open_snapshots: usize,
6366

6467
/// When we add a R1 == R2 constriant, we currently add (a) edges
6568
/// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this
@@ -254,15 +257,7 @@ struct TwoRegions<'tcx> {
254257
}
255258

256259
#[derive(Copy, Clone, PartialEq)]
257-
enum UndoLogEntry<'tcx> {
258-
/// Pushed when we start a snapshot.
259-
OpenSnapshot,
260-
261-
/// Replaces an `OpenSnapshot` when a snapshot is committed, but
262-
/// that snapshot is not the root. If the root snapshot is
263-
/// unrolled, all nested snapshots must be committed.
264-
CommitedSnapshot,
265-
260+
enum UndoLog<'tcx> {
266261
/// We added `RegionVid`
267262
AddVar(RegionVid),
268263

@@ -387,6 +382,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
387382
glbs,
388383
bound_count: _,
389384
undo_log: _,
385+
num_open_snapshots: _,
390386
unification_table,
391387
any_unifications,
392388
} = self;
@@ -415,53 +411,60 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
415411
}
416412

417413
fn in_snapshot(&self) -> bool {
418-
!self.undo_log.is_empty()
414+
self.num_open_snapshots > 0
419415
}
420416

421417
pub fn start_snapshot(&mut self) -> RegionSnapshot {
422418
let length = self.undo_log.len();
423419
debug!("RegionConstraintCollector: start_snapshot({})", length);
424-
self.undo_log.push(OpenSnapshot);
420+
self.num_open_snapshots += 1;
425421
RegionSnapshot {
426422
length,
427423
region_snapshot: self.unification_table.snapshot(),
428424
any_unifications: self.any_unifications,
429425
}
430426
}
431427

428+
fn assert_open_snapshot(&self, snapshot: &RegionSnapshot) {
429+
assert!(self.undo_log.len() >= snapshot.length);
430+
assert!(self.num_open_snapshots > 0);
431+
}
432+
432433
pub fn commit(&mut self, snapshot: RegionSnapshot) {
433434
debug!("RegionConstraintCollector: commit({})", snapshot.length);
434-
assert!(self.undo_log.len() > snapshot.length);
435-
assert!(self.undo_log[snapshot.length] == OpenSnapshot);
435+
self.assert_open_snapshot(&snapshot);
436436

437-
if snapshot.length == 0 {
437+
if self.num_open_snapshots == 1 {
438+
// The root snapshot. It's safe to clear the undo log because
439+
// there's no snapshot further out that we might need to roll back
440+
// to.
441+
assert!(snapshot.length == 0);
438442
self.undo_log.clear();
439-
} else {
440-
(*self.undo_log)[snapshot.length] = CommitedSnapshot;
441443
}
444+
445+
self.num_open_snapshots -= 1;
446+
442447
self.unification_table.commit(snapshot.region_snapshot);
443448
}
444449

445450
pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
446451
debug!("RegionConstraintCollector: rollback_to({:?})", snapshot);
447-
assert!(self.undo_log.len() > snapshot.length);
448-
assert!(self.undo_log[snapshot.length] == OpenSnapshot);
449-
while self.undo_log.len() > snapshot.length + 1 {
452+
self.assert_open_snapshot(&snapshot);
453+
454+
while self.undo_log.len() > snapshot.length {
450455
let undo_entry = self.undo_log.pop().unwrap();
451456
self.rollback_undo_entry(undo_entry);
452457
}
453-
let c = self.undo_log.pop().unwrap();
454-
assert!(c == OpenSnapshot);
458+
459+
self.num_open_snapshots -= 1;
460+
455461
self.unification_table.rollback_to(snapshot.region_snapshot);
456462
self.any_unifications = snapshot.any_unifications;
457463
}
458464

459-
fn rollback_undo_entry(&mut self, undo_entry: UndoLogEntry<'tcx>) {
465+
fn rollback_undo_entry(&mut self, undo_entry: UndoLog<'tcx>) {
460466
match undo_entry {
461-
OpenSnapshot => {
462-
panic!("Failure to observe stack discipline");
463-
}
464-
Purged | CommitedSnapshot => {
467+
Purged => {
465468
// nothing to do here
466469
}
467470
AddVar(vid) => {
@@ -521,15 +524,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
521524
/// in `skols`. This is used after a higher-ranked operation
522525
/// completes to remove all trace of the placeholder regions
523526
/// created in that time.
524-
pub fn pop_placeholders(
525-
&mut self,
526-
placeholders: &FxHashSet<ty::Region<'tcx>>,
527-
snapshot: &RegionSnapshot,
528-
) {
527+
pub fn pop_placeholders(&mut self, placeholders: &FxHashSet<ty::Region<'tcx>>) {
529528
debug!("pop_placeholders(placeholders={:?})", placeholders);
530529

531530
assert!(self.in_snapshot());
532-
assert!(self.undo_log[snapshot.length] == OpenSnapshot);
533531

534532
let constraints_to_kill: Vec<usize> = self.undo_log
535533
.iter()
@@ -548,7 +546,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
548546

549547
fn kill_constraint<'tcx>(
550548
placeholders: &FxHashSet<ty::Region<'tcx>>,
551-
undo_entry: &UndoLogEntry<'tcx>,
549+
undo_entry: &UndoLog<'tcx>,
552550
) -> bool {
553551
match undo_entry {
554552
&AddConstraint(Constraint::VarSubVar(..)) => false,
@@ -562,7 +560,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
562560
&AddCombination(_, ref two_regions) => {
563561
placeholders.contains(&two_regions.a) || placeholders.contains(&two_regions.b)
564562
}
565-
&AddVar(..) | &OpenSnapshot | &Purged | &CommitedSnapshot => false,
563+
&AddVar(..) | &Purged => false,
566564
}
567565
}
568566
}

‎src/librustc/infer/region_constraints/taint.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ impl<'tcx> TaintSet<'tcx> {
2929
pub(super) fn fixed_point(
3030
&mut self,
3131
tcx: TyCtxt<'_, '_, 'tcx>,
32-
undo_log: &[UndoLogEntry<'tcx>],
32+
undo_log: &[UndoLog<'tcx>],
3333
verifys: &[Verify<'tcx>],
3434
) {
3535
let mut prev_len = 0;
@@ -65,8 +65,7 @@ impl<'tcx> TaintSet<'tcx> {
6565
"we never add verifications while doing higher-ranked things",
6666
)
6767
}
68-
&Purged | &AddCombination(..) | &AddVar(..) | &OpenSnapshot
69-
| &CommitedSnapshot => {}
68+
&Purged | &AddCombination(..) | &AddVar(..) => {}
7069
}
7170
}
7271
}

‎src/librustc/traits/project.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,15 +1652,15 @@ impl<'tcx> ProjectionCache<'tcx> {
16521652
}
16531653

16541654
pub fn rollback_to(&mut self, snapshot: ProjectionCacheSnapshot) {
1655-
self.map.rollback_to(&snapshot.snapshot);
1655+
self.map.rollback_to(snapshot.snapshot);
16561656
}
16571657

16581658
pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) {
16591659
self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_placeholders());
16601660
}
16611661

1662-
pub fn commit(&mut self, snapshot: &ProjectionCacheSnapshot) {
1663-
self.map.commit(&snapshot.snapshot);
1662+
pub fn commit(&mut self, snapshot: ProjectionCacheSnapshot) {
1663+
self.map.commit(snapshot.snapshot);
16641664
}
16651665

16661666
/// Try to start normalize `key`; returns an error if
@@ -1714,12 +1714,8 @@ impl<'tcx> ProjectionCache<'tcx> {
17141714
/// to be a NormalizedTy.
17151715
pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &NormalizedTy<'tcx>) {
17161716
// We want to insert `ty` with no obligations. If the existing value
1717-
// already has no obligations (as is common) we can use `insert_noop`
1718-
// to do a minimal amount of work -- the HashMap insertion is skipped,
1719-
// and minimal changes are made to the undo log.
1720-
if ty.obligations.is_empty() {
1721-
self.map.insert_noop();
1722-
} else {
1717+
// already has no obligations (as is common) we don't insert anything.
1718+
if !ty.obligations.is_empty() {
17231719
self.map.insert(key, ProjectionCacheEntry::NormalizedTy(Normalized {
17241720
value: ty.value,
17251721
obligations: vec![]

‎src/librustc_data_structures/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ path = "lib.rs"
99
crate-type = ["dylib"]
1010

1111
[dependencies]
12-
ena = "0.10.1"
12+
ena = "0.11"
1313
log = "0.4"
1414
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
1515
serialize = { path = "../libserialize" }

‎src/librustc_data_structures/snapshot_map/mod.rs

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct SnapshotMap<K, V>
2121
{
2222
map: FxHashMap<K, V>,
2323
undo_log: Vec<UndoLog<K, V>>,
24+
num_open_snapshots: usize,
2425
}
2526

2627
// HACK(eddyb) manual impl avoids `Default` bounds on `K` and `V`.
@@ -31,6 +32,7 @@ impl<K, V> Default for SnapshotMap<K, V>
3132
SnapshotMap {
3233
map: Default::default(),
3334
undo_log: Default::default(),
35+
num_open_snapshots: 0,
3436
}
3537
}
3638
}
@@ -40,11 +42,9 @@ pub struct Snapshot {
4042
}
4143

4244
enum UndoLog<K, V> {
43-
OpenSnapshot,
44-
CommittedSnapshot,
4545
Inserted(K),
4646
Overwrite(K, V),
47-
Noop,
47+
Purged,
4848
}
4949

5050
impl<K, V> SnapshotMap<K, V>
@@ -53,35 +53,34 @@ impl<K, V> SnapshotMap<K, V>
5353
pub fn clear(&mut self) {
5454
self.map.clear();
5555
self.undo_log.clear();
56+
self.num_open_snapshots = 0;
57+
}
58+
59+
fn in_snapshot(&self) -> bool {
60+
self.num_open_snapshots > 0
5661
}
5762

5863
pub fn insert(&mut self, key: K, value: V) -> bool {
5964
match self.map.insert(key.clone(), value) {
6065
None => {
61-
if !self.undo_log.is_empty() {
66+
if self.in_snapshot() {
6267
self.undo_log.push(UndoLog::Inserted(key));
6368
}
6469
true
6570
}
6671
Some(old_value) => {
67-
if !self.undo_log.is_empty() {
72+
if self.in_snapshot() {
6873
self.undo_log.push(UndoLog::Overwrite(key, old_value));
6974
}
7075
false
7176
}
7277
}
7378
}
7479

75-
pub fn insert_noop(&mut self) {
76-
if !self.undo_log.is_empty() {
77-
self.undo_log.push(UndoLog::Noop);
78-
}
79-
}
80-
8180
pub fn remove(&mut self, key: K) -> bool {
8281
match self.map.remove(&key) {
8382
Some(old_value) => {
84-
if !self.undo_log.is_empty() {
83+
if self.in_snapshot() {
8584
self.undo_log.push(UndoLog::Overwrite(key, old_value));
8685
}
8786
true
@@ -95,27 +94,27 @@ impl<K, V> SnapshotMap<K, V>
9594
}
9695

9796
pub fn snapshot(&mut self) -> Snapshot {
98-
self.undo_log.push(UndoLog::OpenSnapshot);
99-
let len = self.undo_log.len() - 1;
97+
let len = self.undo_log.len();
98+
self.num_open_snapshots += 1;
10099
Snapshot { len }
101100
}
102101

103102
fn assert_open_snapshot(&self, snapshot: &Snapshot) {
104-
assert!(snapshot.len < self.undo_log.len());
105-
assert!(match self.undo_log[snapshot.len] {
106-
UndoLog::OpenSnapshot => true,
107-
_ => false,
108-
});
103+
assert!(self.undo_log.len() >= snapshot.len);
104+
assert!(self.num_open_snapshots > 0);
109105
}
110106

111-
pub fn commit(&mut self, snapshot: &Snapshot) {
112-
self.assert_open_snapshot(snapshot);
113-
if snapshot.len == 0 {
114-
// The root snapshot.
115-
self.undo_log.truncate(0);
116-
} else {
117-
self.undo_log[snapshot.len] = UndoLog::CommittedSnapshot;
107+
pub fn commit(&mut self, snapshot: Snapshot) {
108+
self.assert_open_snapshot(&snapshot);
109+
if self.num_open_snapshots == 1 {
110+
// The root snapshot. It's safe to clear the undo log because
111+
// there's no snapshot further out that we might need to roll back
112+
// to.
113+
assert!(snapshot.len == 0);
114+
self.undo_log.clear();
118115
}
116+
117+
self.num_open_snapshots -= 1;
119118
}
120119

121120
pub fn partial_rollback<F>(&mut self,
@@ -124,45 +123,32 @@ impl<K, V> SnapshotMap<K, V>
124123
where F: Fn(&K) -> bool
125124
{
126125
self.assert_open_snapshot(snapshot);
127-
for i in (snapshot.len + 1..self.undo_log.len()).rev() {
126+
for i in (snapshot.len .. self.undo_log.len()).rev() {
128127
let reverse = match self.undo_log[i] {
129-
UndoLog::OpenSnapshot => false,
130-
UndoLog::CommittedSnapshot => false,
131-
UndoLog::Noop => false,
128+
UndoLog::Purged => false,
132129
UndoLog::Inserted(ref k) => should_revert_key(k),
133130
UndoLog::Overwrite(ref k, _) => should_revert_key(k),
134131
};
135132

136133
if reverse {
137-
let entry = mem::replace(&mut self.undo_log[i], UndoLog::Noop);
134+
let entry = mem::replace(&mut self.undo_log[i], UndoLog::Purged);
138135
self.reverse(entry);
139136
}
140137
}
141138
}
142139

143-
pub fn rollback_to(&mut self, snapshot: &Snapshot) {
144-
self.assert_open_snapshot(snapshot);
145-
while self.undo_log.len() > snapshot.len + 1 {
140+
pub fn rollback_to(&mut self, snapshot: Snapshot) {
141+
self.assert_open_snapshot(&snapshot);
142+
while self.undo_log.len() > snapshot.len {
146143
let entry = self.undo_log.pop().unwrap();
147144
self.reverse(entry);
148145
}
149146

150-
let v = self.undo_log.pop().unwrap();
151-
assert!(match v {
152-
UndoLog::OpenSnapshot => true,
153-
_ => false,
154-
});
155-
assert!(self.undo_log.len() == snapshot.len);
147+
self.num_open_snapshots -= 1;
156148
}
157149

158150
fn reverse(&mut self, entry: UndoLog<K, V>) {
159151
match entry {
160-
UndoLog::OpenSnapshot => {
161-
panic!("cannot rollback an uncommitted snapshot");
162-
}
163-
164-
UndoLog::CommittedSnapshot => {}
165-
166152
UndoLog::Inserted(key) => {
167153
self.map.remove(&key);
168154
}
@@ -171,7 +157,7 @@ impl<K, V> SnapshotMap<K, V>
171157
self.map.insert(key, old_value);
172158
}
173159

174-
UndoLog::Noop => {}
160+
UndoLog::Purged => {}
175161
}
176162
}
177163
}

‎src/librustc_data_structures/snapshot_map/test.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ fn basic() {
1717
let snapshot = map.snapshot();
1818
map.insert(22, "thirty-three");
1919
assert_eq!(map[&22], "thirty-three");
20-
map.insert(44, "fourty-four");
21-
assert_eq!(map[&44], "fourty-four");
20+
map.insert(44, "forty-four");
21+
assert_eq!(map[&44], "forty-four");
2222
assert_eq!(map.get(&33), None);
23-
map.rollback_to(&snapshot);
23+
map.rollback_to(snapshot);
2424
assert_eq!(map[&22], "twenty-two");
2525
assert_eq!(map.get(&33), None);
2626
assert_eq!(map.get(&44), None);
@@ -32,8 +32,11 @@ fn out_of_order() {
3232
let mut map = SnapshotMap::default();
3333
map.insert(22, "twenty-two");
3434
let snapshot1 = map.snapshot();
35-
let _snapshot2 = map.snapshot();
36-
map.rollback_to(&snapshot1);
35+
map.insert(33, "thirty-three");
36+
let snapshot2 = map.snapshot();
37+
map.insert(44, "forty-four");
38+
map.rollback_to(snapshot1); // bogus, but accepted
39+
map.rollback_to(snapshot2); // asserts
3740
}
3841

3942
#[test]
@@ -43,8 +46,8 @@ fn nested_commit_then_rollback() {
4346
let snapshot1 = map.snapshot();
4447
let snapshot2 = map.snapshot();
4548
map.insert(22, "thirty-three");
46-
map.commit(&snapshot2);
49+
map.commit(snapshot2);
4750
assert_eq!(map[&22], "thirty-three");
48-
map.rollback_to(&snapshot1);
51+
map.rollback_to(snapshot1);
4952
assert_eq!(map[&22], "twenty-two");
5053
}

0 commit comments

Comments
 (0)
Please sign in to comment.