@@ -3,6 +3,7 @@ mod overflow;
3
3
4
4
use self :: cache:: ProvisionalEntry ;
5
5
use super :: { CanonicalGoal , Certainty , MaybeCause , QueryResult } ;
6
+ pub ( super ) use crate :: solve:: search_graph:: overflow:: OverflowHandler ;
6
7
use cache:: ProvisionalCache ;
7
8
use overflow:: OverflowData ;
8
9
use rustc_index:: vec:: IndexVec ;
@@ -46,7 +47,7 @@ impl<'tcx> SearchGraph<'tcx> {
46
47
///
47
48
/// This correctly updates the provisional cache if there is a cycle.
48
49
#[ instrument( level = "debug" , skip( self , tcx) , ret) ]
49
- pub ( super ) fn try_push_stack (
50
+ fn try_push_stack (
50
51
& mut self ,
51
52
tcx : TyCtxt < ' tcx > ,
52
53
goal : CanonicalGoal < ' tcx > ,
@@ -121,19 +122,19 @@ impl<'tcx> SearchGraph<'tcx> {
121
122
///
122
123
/// FIXME: Refer to the rustc-dev-guide entry once it exists.
123
124
#[ instrument( level = "debug" , skip( self , tcx, actual_goal) , ret) ]
124
- pub ( super ) fn try_finalize_goal (
125
+ fn try_finalize_goal (
125
126
& mut self ,
126
127
tcx : TyCtxt < ' tcx > ,
127
128
actual_goal : CanonicalGoal < ' tcx > ,
128
129
response : QueryResult < ' tcx > ,
129
130
) -> bool {
130
- let StackElem { goal, has_been_used } = self . stack . pop ( ) . unwrap ( ) ;
131
+ let stack_elem = self . stack . pop ( ) . unwrap ( ) ;
132
+ let StackElem { goal, has_been_used } = stack_elem;
131
133
assert_eq ! ( goal, actual_goal) ;
132
134
133
135
let cache = & mut self . provisional_cache ;
134
136
let provisional_entry_index = * cache. lookup_table . get ( & goal) . unwrap ( ) ;
135
137
let provisional_entry = & mut cache. entries [ provisional_entry_index] ;
136
- let depth = provisional_entry. depth ;
137
138
// We eagerly update the response in the cache here. If we have to reevaluate
138
139
// this goal we use the new response when hitting a cycle, and we definitely
139
140
// want to access the final response whenever we look at the cache.
@@ -157,29 +158,72 @@ impl<'tcx> SearchGraph<'tcx> {
157
158
self . stack . push ( StackElem { goal, has_been_used : false } ) ;
158
159
false
159
160
} else {
160
- // If not, we're done with this goal.
161
- //
162
- // Check whether that this goal doesn't depend on a goal deeper on the stack
163
- // and if so, move it and all nested goals to the global cache.
164
- //
165
- // Note that if any nested goal were to depend on something deeper on the stack,
166
- // this would have also updated the depth of the current goal.
167
- if depth == self . stack . next_index ( ) {
168
- for ( i, entry) in cache. entries . drain_enumerated ( provisional_entry_index. index ( ) ..)
169
- {
170
- let actual_index = cache. lookup_table . remove ( & entry. goal ) ;
171
- debug_assert_eq ! ( Some ( i) , actual_index) ;
172
- debug_assert ! ( entry. depth == depth) ;
173
- cache:: try_move_finished_goal_to_global_cache (
174
- tcx,
175
- & mut self . overflow_data ,
176
- & self . stack ,
177
- entry. goal ,
178
- entry. response ,
179
- ) ;
180
- }
181
- }
161
+ self . try_move_finished_goal_to_global_cache ( tcx, stack_elem) ;
182
162
true
183
163
}
184
164
}
165
+
166
+ fn try_move_finished_goal_to_global_cache (
167
+ & mut self ,
168
+ tcx : TyCtxt < ' tcx > ,
169
+ stack_elem : StackElem < ' tcx > ,
170
+ ) {
171
+ let StackElem { goal, .. } = stack_elem;
172
+ let cache = & mut self . provisional_cache ;
173
+ let provisional_entry_index = * cache. lookup_table . get ( & goal) . unwrap ( ) ;
174
+ let provisional_entry = & mut cache. entries [ provisional_entry_index] ;
175
+ let depth = provisional_entry. depth ;
176
+
177
+ // If not, we're done with this goal.
178
+ //
179
+ // Check whether that this goal doesn't depend on a goal deeper on the stack
180
+ // and if so, move it and all nested goals to the global cache.
181
+ //
182
+ // Note that if any nested goal were to depend on something deeper on the stack,
183
+ // this would have also updated the depth of the current goal.
184
+ if depth == self . stack . next_index ( ) {
185
+ for ( i, entry) in cache. entries . drain_enumerated ( provisional_entry_index. index ( ) ..) {
186
+ let actual_index = cache. lookup_table . remove ( & entry. goal ) ;
187
+ debug_assert_eq ! ( Some ( i) , actual_index) ;
188
+ debug_assert ! ( entry. depth == depth) ;
189
+ cache:: try_move_finished_goal_to_global_cache (
190
+ tcx,
191
+ & mut self . overflow_data ,
192
+ & self . stack ,
193
+ entry. goal ,
194
+ entry. response ,
195
+ ) ;
196
+ }
197
+ }
198
+ }
199
+
200
+ pub ( super ) fn with_new_goal (
201
+ & mut self ,
202
+ tcx : TyCtxt < ' tcx > ,
203
+ canonical_goal : CanonicalGoal < ' tcx > ,
204
+ mut loop_body : impl FnMut ( & mut Self ) -> QueryResult < ' tcx > ,
205
+ ) -> QueryResult < ' tcx > {
206
+ match self . try_push_stack ( tcx, canonical_goal) {
207
+ Ok ( ( ) ) => { }
208
+ // Our goal is already on the stack, eager return.
209
+ Err ( response) => return response,
210
+ }
211
+
212
+ self . repeat_while_none (
213
+ |this| {
214
+ let result = this. deal_with_overflow ( tcx, canonical_goal) ;
215
+ let stack_elem = this. stack . pop ( ) . unwrap ( ) ;
216
+ this. try_move_finished_goal_to_global_cache ( tcx, stack_elem) ;
217
+ result
218
+ } ,
219
+ |this| {
220
+ let result = loop_body ( this) ;
221
+ if this. try_finalize_goal ( tcx, canonical_goal, result) {
222
+ Some ( result)
223
+ } else {
224
+ None
225
+ }
226
+ } ,
227
+ )
228
+ }
185
229
}
0 commit comments