11
11
use dep_graph:: DepGraph ;
12
12
use middle:: infer:: InferCtxt ;
13
13
use middle:: ty:: { self , Ty , TypeFoldable } ;
14
- use rustc_data_structures:: obligation_forest:: { Backtrace , ObligationForest , Error } ;
14
+ use rustc_data_structures:: obligation_forest:: { Backtrace , ObligationForest , UndoLog , Error } ;
15
+ use rustc_data_structures:: undoable:: { Undoable , UndoableTracker , Undoer } ;
16
+ use std:: cell:: RefCell ;
15
17
use std:: iter;
18
+ use std:: rc:: Rc ;
16
19
use syntax:: ast;
17
20
use util:: common:: ErrorReported ;
18
21
use util:: nodemap:: { FnvHashMap , FnvHashSet , NodeMap } ;
@@ -31,14 +34,18 @@ use super::select::SelectionContext;
31
34
use super :: Unimplemented ;
32
35
use super :: util:: predicate_for_builtin_bound;
33
36
37
+ pub type ObligationForestUndoLog < ' tcx > = UndoLog < PendingPredicateObligation < ' tcx > ,
38
+ LocalFulfilledPredicates < ' tcx > > ;
39
+
34
40
pub struct GlobalFulfilledPredicates < ' tcx > {
35
41
set : FnvHashSet < ty:: PolyTraitPredicate < ' tcx > > ,
36
42
dep_graph : DepGraph ,
37
43
}
38
44
39
- #[ derive( Debug ) ]
45
+ #[ derive( Debug , Clone ) ]
40
46
pub struct LocalFulfilledPredicates < ' tcx > {
41
- set : FnvHashSet < ty:: Predicate < ' tcx > >
47
+ set : FnvHashSet < ty:: Predicate < ' tcx > > ,
48
+ log : Option < ( Rc < RefCell < ObligationForestUndoLog < ' tcx > > > , usize ) > ,
42
49
}
43
50
44
51
/// The fulfillment context is used to drive trait resolution. It
@@ -110,6 +117,12 @@ pub struct PendingPredicateObligation<'tcx> {
110
117
pub stalled_on : Vec < Ty < ' tcx > > ,
111
118
}
112
119
120
+ #[ derive( Debug ) ]
121
+ pub enum LocalFulfilledPredicatesAction < ' tcx > {
122
+ Add { key : ty:: Predicate < ' tcx > }
123
+ }
124
+
125
+
113
126
impl < ' tcx > FulfillmentContext < ' tcx > {
114
127
/// Creates a new fulfillment context.
115
128
pub fn new ( ) -> FulfillmentContext < ' tcx > {
@@ -670,19 +683,46 @@ fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
670
683
impl < ' tcx > LocalFulfilledPredicates < ' tcx > {
671
684
pub fn new ( ) -> LocalFulfilledPredicates < ' tcx > {
672
685
LocalFulfilledPredicates {
673
- set : FnvHashSet ( )
686
+ set : FnvHashSet ( ) ,
687
+ log : None ,
674
688
}
675
689
}
676
690
677
691
fn is_duplicate_or_add ( & mut self , key : & ty:: Predicate < ' tcx > ) -> bool {
692
+ let insert_result = self . set . insert ( key. clone ( ) ) ;
693
+ if insert_result {
694
+ if let Some ( ( ref log, id) ) = self . log {
695
+ ( * log) . borrow_mut ( ) . push_action (
696
+ id, LocalFulfilledPredicatesAction :: Add { key : key. clone ( ) } ) ;
697
+ }
698
+ }
678
699
// For a `LocalFulfilledPredicates`, if we find a match, we
679
700
// don't need to add a read edge to the dep-graph. This is
680
701
// because it means that the predicate has already been
681
702
// considered by this `FulfillmentContext`, and hence the
682
703
// containing task will already have an edge. (Here we are
683
704
// assuming each `FulfillmentContext` only gets used from one
684
705
// task; but to do otherwise makes no sense)
685
- !self . set . insert ( key. clone ( ) )
706
+ !insert_result
707
+ }
708
+ }
709
+
710
+ impl < ' tcx > Undoer for LocalFulfilledPredicatesAction < ' tcx > {
711
+ type Undoable = LocalFulfilledPredicates < ' tcx > ;
712
+ fn undo ( self , predicates : & mut LocalFulfilledPredicates < ' tcx > ) {
713
+ match self {
714
+ LocalFulfilledPredicatesAction :: Add { key } => {
715
+ assert ! ( predicates. set. remove( & key) ) ;
716
+ }
717
+ }
718
+ }
719
+ }
720
+
721
+ impl < ' tcx > Undoable for LocalFulfilledPredicates < ' tcx > {
722
+ type Undoer = LocalFulfilledPredicatesAction < ' tcx > ;
723
+ type Tracker = ObligationForestUndoLog < ' tcx > ;
724
+ fn register_tracker ( & mut self , log : Rc < RefCell < Self :: Tracker > > , id : usize ) {
725
+ self . log = Some ( ( log, id) ) ;
686
726
}
687
727
}
688
728
0 commit comments