@@ -3,6 +3,7 @@ mod overflow;
33
44use self :: cache:: ProvisionalEntry ;
55use super :: { CanonicalGoal , Certainty , MaybeCause , QueryResult } ;
6+ pub ( super ) use crate :: solve:: search_graph:: overflow:: OverflowHandler ;
67use cache:: ProvisionalCache ;
78use overflow:: OverflowData ;
89use rustc_index:: vec:: IndexVec ;
@@ -46,7 +47,7 @@ impl<'tcx> SearchGraph<'tcx> {
4647 ///
4748 /// This correctly updates the provisional cache if there is a cycle.
4849 #[ instrument( level = "debug" , skip( self , tcx) , ret) ]
49- pub ( super ) fn try_push_stack (
50+ fn try_push_stack (
5051 & mut self ,
5152 tcx : TyCtxt < ' tcx > ,
5253 goal : CanonicalGoal < ' tcx > ,
@@ -121,19 +122,19 @@ impl<'tcx> SearchGraph<'tcx> {
121122 ///
122123 /// FIXME: Refer to the rustc-dev-guide entry once it exists.
123124 #[ instrument( level = "debug" , skip( self , tcx, actual_goal) , ret) ]
124- pub ( super ) fn try_finalize_goal (
125+ fn try_finalize_goal (
125126 & mut self ,
126127 tcx : TyCtxt < ' tcx > ,
127128 actual_goal : CanonicalGoal < ' tcx > ,
128129 response : QueryResult < ' tcx > ,
129130 ) -> 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;
131133 assert_eq ! ( goal, actual_goal) ;
132134
133135 let cache = & mut self . provisional_cache ;
134136 let provisional_entry_index = * cache. lookup_table . get ( & goal) . unwrap ( ) ;
135137 let provisional_entry = & mut cache. entries [ provisional_entry_index] ;
136- let depth = provisional_entry. depth ;
137138 // We eagerly update the response in the cache here. If we have to reevaluate
138139 // this goal we use the new response when hitting a cycle, and we definitely
139140 // want to access the final response whenever we look at the cache.
@@ -157,29 +158,72 @@ impl<'tcx> SearchGraph<'tcx> {
157158 self . stack . push ( StackElem { goal, has_been_used : false } ) ;
158159 false
159160 } 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) ;
182162 true
183163 }
184164 }
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+ }
185229}
0 commit comments