11
11
//! See README.md
12
12
13
13
use self :: CombineMapType :: * ;
14
- use self :: UndoLogEntry :: * ;
14
+ use self :: UndoLog :: * ;
15
15
16
16
use super :: unify_key;
17
17
use super :: { MiscVariable , RegionVariableOrigin , SubregionOrigin } ;
@@ -52,14 +52,17 @@ 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.
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 ,
63
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
@@ -254,15 +257,7 @@ struct TwoRegions<'tcx> {
254
257
}
255
258
256
259
#[ 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 > {
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,53 +411,60 @@ 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 ( ) ,
428
424
any_unifications : self . any_unifications ,
429
425
}
430
426
}
431
427
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
+
432
433
pub fn commit ( & mut self , snapshot : RegionSnapshot ) {
433
434
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) ;
436
436
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 ) ;
438
442
self . undo_log . clear ( ) ;
439
- } else {
440
- ( * self . undo_log ) [ snapshot. length ] = CommitedSnapshot ;
441
443
}
444
+
445
+ self . num_open_snapshots -= 1 ;
446
+
442
447
self . unification_table . commit ( snapshot. region_snapshot ) ;
443
448
}
444
449
445
450
pub fn rollback_to ( & mut self , snapshot : RegionSnapshot ) {
446
451
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 {
450
455
let undo_entry = self . undo_log . pop ( ) . unwrap ( ) ;
451
456
self . rollback_undo_entry ( undo_entry) ;
452
457
}
453
- let c = self . undo_log . pop ( ) . unwrap ( ) ;
454
- assert ! ( c == OpenSnapshot ) ;
458
+
459
+ self . num_open_snapshots -= 1 ;
460
+
455
461
self . unification_table . rollback_to ( snapshot. region_snapshot ) ;
456
462
self . any_unifications = snapshot. any_unifications ;
457
463
}
458
464
459
- fn rollback_undo_entry ( & mut self , undo_entry : UndoLogEntry < ' tcx > ) {
465
+ fn rollback_undo_entry ( & mut self , undo_entry : UndoLog < ' tcx > ) {
460
466
match undo_entry {
461
- OpenSnapshot => {
462
- panic ! ( "Failure to observe stack discipline" ) ;
463
- }
464
- Purged | CommitedSnapshot => {
467
+ Purged => {
465
468
// nothing to do here
466
469
}
467
470
AddVar ( vid) => {
@@ -521,15 +524,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
521
524
/// in `skols`. This is used after a higher-ranked operation
522
525
/// completes to remove all trace of the placeholder regions
523
526
/// 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 > > ) {
529
528
debug ! ( "pop_placeholders(placeholders={:?})" , placeholders) ;
530
529
531
530
assert ! ( self . in_snapshot( ) ) ;
532
- assert ! ( self . undo_log[ snapshot. length] == OpenSnapshot ) ;
533
531
534
532
let constraints_to_kill: Vec < usize > = self . undo_log
535
533
. iter ( )
@@ -548,7 +546,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
548
546
549
547
fn kill_constraint < ' tcx > (
550
548
placeholders : & FxHashSet < ty:: Region < ' tcx > > ,
551
- undo_entry : & UndoLogEntry < ' tcx > ,
549
+ undo_entry : & UndoLog < ' tcx > ,
552
550
) -> bool {
553
551
match undo_entry {
554
552
& AddConstraint ( Constraint :: VarSubVar ( ..) ) => false ,
@@ -562,7 +560,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
562
560
& AddCombination ( _, ref two_regions) => {
563
561
placeholders. contains ( & two_regions. a ) || placeholders. contains ( & two_regions. b )
564
562
}
565
- & AddVar ( ..) | & OpenSnapshot | & Purged | & CommitedSnapshot => false ,
563
+ & AddVar ( ..) | & Purged => false ,
566
564
}
567
565
}
568
566
}
0 commit comments