@@ -52,15 +52,18 @@ pub struct RegionConstraintCollector<'tcx> {
52
52
53
53
/// The undo log records actions that might later be undone.
54
54
///
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
56
56
/// 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.
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.
62
61
undo_log : Vec < UndoLog < ' tcx > > ,
63
62
63
+ /// The number of open snapshots, i.e. those that haven't been committed or
64
+ /// rolled back.
65
+ num_open_snapshots : usize ,
66
+
64
67
/// When we add a R1 == R2 constriant, we currently add (a) edges
65
68
/// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this
66
69
/// table. You can then call `opportunistic_resolve_var` early
@@ -255,14 +258,6 @@ struct TwoRegions<'tcx> {
255
258
256
259
#[ derive( Copy , Clone , PartialEq ) ]
257
260
enum UndoLog < ' 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
-
266
261
/// We added `RegionVid`
267
262
AddVar ( RegionVid ) ,
268
263
@@ -387,6 +382,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
387
382
glbs,
388
383
bound_count : _,
389
384
undo_log : _,
385
+ num_open_snapshots : _,
390
386
unification_table,
391
387
any_unifications,
392
388
} = self ;
@@ -415,13 +411,13 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
415
411
}
416
412
417
413
fn in_snapshot ( & self ) -> bool {
418
- ! self . undo_log . is_empty ( )
414
+ self . num_open_snapshots > 0
419
415
}
420
416
421
417
pub fn start_snapshot ( & mut self ) -> RegionSnapshot {
422
418
let length = self . undo_log . len ( ) ;
423
419
debug ! ( "RegionConstraintCollector: start_snapshot({})" , length) ;
424
- self . undo_log . push ( OpenSnapshot ) ;
420
+ self . num_open_snapshots += 1 ;
425
421
RegionSnapshot {
426
422
length,
427
423
region_snapshot : self . unification_table . snapshot ( ) ,
@@ -430,41 +426,45 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
430
426
}
431
427
432
428
fn assert_open_snapshot ( & self , snapshot : & RegionSnapshot ) {
433
- assert ! ( self . undo_log. len( ) > snapshot. length) ;
434
- assert ! ( self . undo_log [ snapshot . length ] == OpenSnapshot ) ;
429
+ assert ! ( self . undo_log. len( ) >= snapshot. length) ;
430
+ assert ! ( self . num_open_snapshots > 0 ) ;
435
431
}
436
432
437
433
pub fn commit ( & mut self , snapshot : RegionSnapshot ) {
438
434
debug ! ( "RegionConstraintCollector: commit({})" , snapshot. length) ;
439
435
self . assert_open_snapshot ( & snapshot) ;
440
436
441
- 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 ) ;
442
442
self . undo_log . clear ( ) ;
443
- } else {
444
- ( * self . undo_log ) [ snapshot. length ] = CommitedSnapshot ;
445
443
}
444
+
445
+ self . num_open_snapshots -= 1 ;
446
+
446
447
self . unification_table . commit ( snapshot. region_snapshot ) ;
447
448
}
448
449
449
450
pub fn rollback_to ( & mut self , snapshot : RegionSnapshot ) {
450
451
debug ! ( "RegionConstraintCollector: rollback_to({:?})" , snapshot) ;
451
452
self . assert_open_snapshot ( & snapshot) ;
452
- while self . undo_log . len ( ) > snapshot. length + 1 {
453
+
454
+ while self . undo_log . len ( ) > snapshot. length {
453
455
let undo_entry = self . undo_log . pop ( ) . unwrap ( ) ;
454
456
self . rollback_undo_entry ( undo_entry) ;
455
457
}
456
- let c = self . undo_log . pop ( ) . unwrap ( ) ;
457
- assert ! ( c == OpenSnapshot ) ;
458
+
459
+ self . num_open_snapshots -= 1 ;
460
+
458
461
self . unification_table . rollback_to ( snapshot. region_snapshot ) ;
459
462
self . any_unifications = snapshot. any_unifications ;
460
463
}
461
464
462
465
fn rollback_undo_entry ( & mut self , undo_entry : UndoLog < ' tcx > ) {
463
466
match undo_entry {
464
- OpenSnapshot => {
465
- panic ! ( "Failure to observe stack discipline" ) ;
466
- }
467
- Purged | CommitedSnapshot => {
467
+ Purged => {
468
468
// nothing to do here
469
469
}
470
470
AddVar ( vid) => {
@@ -524,15 +524,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
524
524
/// in `skols`. This is used after a higher-ranked operation
525
525
/// completes to remove all trace of the placeholder regions
526
526
/// created in that time.
527
- pub fn pop_placeholders (
528
- & mut self ,
529
- placeholders : & FxHashSet < ty:: Region < ' tcx > > ,
530
- snapshot : & RegionSnapshot ,
531
- ) {
527
+ pub fn pop_placeholders ( & mut self , placeholders : & FxHashSet < ty:: Region < ' tcx > > ) {
532
528
debug ! ( "pop_placeholders(placeholders={:?})" , placeholders) ;
533
529
534
530
assert ! ( self . in_snapshot( ) ) ;
535
- assert ! ( self . undo_log[ snapshot. length] == OpenSnapshot ) ;
536
531
537
532
let constraints_to_kill: Vec < usize > = self . undo_log
538
533
. iter ( )
@@ -565,7 +560,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
565
560
& AddCombination ( _, ref two_regions) => {
566
561
placeholders. contains ( & two_regions. a ) || placeholders. contains ( & two_regions. b )
567
562
}
568
- & AddVar ( ..) | & OpenSnapshot | & Purged | & CommitedSnapshot => false ,
563
+ & AddVar ( ..) | & Purged => false ,
569
564
}
570
565
}
571
566
}
0 commit comments