1
1
use derive_where:: derive_where;
2
- use rustc_index:: IndexVec ;
3
2
4
- use super :: { AvailableDepth , Cx , StackDepth , StackEntry } ;
5
- use crate :: data_structures:: { HashMap , HashSet } ;
3
+ use super :: { AvailableDepth , Cx , NestedGoals } ;
4
+ use crate :: data_structures:: HashMap ;
6
5
7
6
struct Success < X : Cx > {
8
- result : X :: Tracked < X :: Result > ,
9
7
additional_depth : usize ,
8
+ nested_goals : NestedGoals < X > ,
9
+ result : X :: Tracked < X :: Result > ,
10
+ }
11
+
12
+ struct WithOverflow < X : Cx > {
13
+ nested_goals : NestedGoals < X > ,
14
+ result : X :: Tracked < X :: Result > ,
10
15
}
11
16
12
17
/// The cache entry for a given input.
@@ -17,23 +22,15 @@ struct Success<X: Cx> {
17
22
#[ derive_where( Default ; X : Cx ) ]
18
23
struct CacheEntry < X : Cx > {
19
24
success : Option < Success < X > > ,
20
- /// We have to be careful when caching roots of cycles.
21
- ///
22
- /// See the doc comment of `StackEntry::cycle_participants` for more
23
- /// details.
24
- nested_goals : HashSet < X :: Input > ,
25
- with_overflow : HashMap < usize , X :: Tracked < X :: Result > > ,
25
+ with_overflow : HashMap < usize , WithOverflow < X > > ,
26
26
}
27
27
28
28
#[ derive_where( Debug ; X : Cx ) ]
29
29
pub ( super ) struct CacheData < ' a , X : Cx > {
30
30
pub ( super ) result : X :: Result ,
31
31
pub ( super ) additional_depth : usize ,
32
32
pub ( super ) encountered_overflow : bool ,
33
- // FIXME: This is currently unused, but impacts the design
34
- // by requiring a closure for `Cx::with_global_cache`.
35
- #[ allow( dead_code) ]
36
- pub ( super ) nested_goals : & ' a HashSet < X :: Input > ,
33
+ pub ( super ) nested_goals : & ' a NestedGoals < X > ,
37
34
}
38
35
#[ derive_where( Default ; X : Cx ) ]
39
36
pub struct GlobalCache < X : Cx > {
@@ -52,15 +49,17 @@ impl<X: Cx> GlobalCache<X> {
52
49
53
50
additional_depth : usize ,
54
51
encountered_overflow : bool ,
55
- nested_goals : & HashSet < X :: Input > ,
52
+ nested_goals : NestedGoals < X > ,
56
53
) {
57
54
let result = cx. mk_tracked ( result, dep_node) ;
58
55
let entry = self . map . entry ( input) . or_default ( ) ;
59
- entry. nested_goals . extend ( nested_goals) ;
60
56
if encountered_overflow {
61
- entry. with_overflow . insert ( additional_depth, result) ;
57
+ let with_overflow = WithOverflow { nested_goals, result } ;
58
+ let prev = entry. with_overflow . insert ( additional_depth, with_overflow) ;
59
+ assert ! ( prev. is_none( ) ) ;
62
60
} else {
63
- entry. success = Some ( Success { result, additional_depth } ) ;
61
+ let prev = entry. success . replace ( Success { additional_depth, nested_goals, result } ) ;
62
+ assert ! ( prev. is_none( ) ) ;
64
63
}
65
64
}
66
65
@@ -72,30 +71,37 @@ impl<X: Cx> GlobalCache<X> {
72
71
& ' a self ,
73
72
cx : X ,
74
73
input : X :: Input ,
75
- stack : & IndexVec < StackDepth , StackEntry < X > > ,
76
74
available_depth : AvailableDepth ,
75
+ mut candidate_is_applicable : impl FnMut ( & NestedGoals < X > ) -> bool ,
77
76
) -> Option < CacheData < ' a , X > > {
78
77
let entry = self . map . get ( & input) ?;
79
- if stack. iter ( ) . any ( |e| entry. nested_goals . contains ( & e. input ) ) {
80
- return None ;
78
+ if let Some ( Success { additional_depth, ref nested_goals, ref result } ) = entry. success {
79
+ if available_depth. cache_entry_is_applicable ( additional_depth)
80
+ && candidate_is_applicable ( nested_goals)
81
+ {
82
+ return Some ( CacheData {
83
+ result : cx. get_tracked ( & result) ,
84
+ additional_depth,
85
+ encountered_overflow : false ,
86
+ nested_goals,
87
+ } ) ;
88
+ }
81
89
}
82
90
83
- if let Some ( ref success) = entry. success {
84
- if available_depth. cache_entry_is_applicable ( success. additional_depth ) {
91
+ let additional_depth = available_depth. 0 ;
92
+ if let Some ( WithOverflow { nested_goals, result } ) =
93
+ entry. with_overflow . get ( & additional_depth)
94
+ {
95
+ if candidate_is_applicable ( nested_goals) {
85
96
return Some ( CacheData {
86
- result : cx. get_tracked ( & success . result ) ,
87
- additional_depth : success . additional_depth ,
88
- encountered_overflow : false ,
89
- nested_goals : & entry . nested_goals ,
97
+ result : cx. get_tracked ( result) ,
98
+ additional_depth,
99
+ encountered_overflow : true ,
100
+ nested_goals,
90
101
} ) ;
91
102
}
92
103
}
93
104
94
- entry. with_overflow . get ( & available_depth. 0 ) . map ( |e| CacheData {
95
- result : cx. get_tracked ( e) ,
96
- additional_depth : available_depth. 0 ,
97
- encountered_overflow : true ,
98
- nested_goals : & entry. nested_goals ,
99
- } )
105
+ None
100
106
}
101
107
}
0 commit comments