@@ -52,15 +52,18 @@ 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.
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.
6261 undo_log : Vec < UndoLog < ' tcx > > ,
6362
63+ /// The number of open snapshots, i.e. those that haven't been committed or
64+ /// rolled back.
65+ num_open_snapshots : usize ,
66+
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
6669 /// table. You can then call `opportunistic_resolve_var` early
@@ -255,14 +258,6 @@ struct TwoRegions<'tcx> {
255258
256259#[ derive( Copy , Clone , PartialEq ) ]
257260enum 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-
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,13 +411,13 @@ 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 ( ) ,
@@ -430,41 +426,45 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
430426 }
431427
432428 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 ) ;
435431 }
436432
437433 pub fn commit ( & mut self , snapshot : RegionSnapshot ) {
438434 debug ! ( "RegionConstraintCollector: commit({})" , snapshot. length) ;
439435 self . assert_open_snapshot ( & snapshot) ;
440436
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 ) ;
442442 self . undo_log . clear ( ) ;
443- } else {
444- ( * self . undo_log ) [ snapshot. length ] = CommitedSnapshot ;
445443 }
444+
445+ self . num_open_snapshots -= 1 ;
446+
446447 self . unification_table . commit ( snapshot. region_snapshot ) ;
447448 }
448449
449450 pub fn rollback_to ( & mut self , snapshot : RegionSnapshot ) {
450451 debug ! ( "RegionConstraintCollector: rollback_to({:?})" , snapshot) ;
451452 self . assert_open_snapshot ( & snapshot) ;
452- while self . undo_log . len ( ) > snapshot. length + 1 {
453+
454+ while self . undo_log . len ( ) > snapshot. length {
453455 let undo_entry = self . undo_log . pop ( ) . unwrap ( ) ;
454456 self . rollback_undo_entry ( undo_entry) ;
455457 }
456- let c = self . undo_log . pop ( ) . unwrap ( ) ;
457- assert ! ( c == OpenSnapshot ) ;
458+
459+ self . num_open_snapshots -= 1 ;
460+
458461 self . unification_table . rollback_to ( snapshot. region_snapshot ) ;
459462 self . any_unifications = snapshot. any_unifications ;
460463 }
461464
462465 fn rollback_undo_entry ( & mut self , undo_entry : UndoLog < ' tcx > ) {
463466 match undo_entry {
464- OpenSnapshot => {
465- panic ! ( "Failure to observe stack discipline" ) ;
466- }
467- Purged | CommitedSnapshot => {
467+ Purged => {
468468 // nothing to do here
469469 }
470470 AddVar ( vid) => {
@@ -524,15 +524,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
524524 /// in `skols`. This is used after a higher-ranked operation
525525 /// completes to remove all trace of the placeholder regions
526526 /// 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 > > ) {
532528 debug ! ( "pop_placeholders(placeholders={:?})" , placeholders) ;
533529
534530 assert ! ( self . in_snapshot( ) ) ;
535- assert ! ( self . undo_log[ snapshot. length] == OpenSnapshot ) ;
536531
537532 let constraints_to_kill: Vec < usize > = self . undo_log
538533 . iter ( )
@@ -565,7 +560,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
565560 & AddCombination ( _, ref two_regions) => {
566561 placeholders. contains ( & two_regions. a ) || placeholders. contains ( & two_regions. b )
567562 }
568- & AddVar ( ..) | & OpenSnapshot | & Purged | & CommitedSnapshot => false ,
563+ & AddVar ( ..) | & Purged => false ,
569564 }
570565 }
571566 }
0 commit comments