@@ -134,16 +134,6 @@ impl<I: Interner> SearchGraph<I> {
134134 self . mode
135135 }
136136
137- /// Update the stack and reached depths on cache hits.
138- #[ instrument( level = "trace" , skip( self ) ) ]
139- fn on_cache_hit ( & mut self , additional_depth : usize , encountered_overflow : bool ) {
140- let reached_depth = self . stack . next_index ( ) . plus ( additional_depth) ;
141- if let Some ( last) = self . stack . raw . last_mut ( ) {
142- last. reached_depth = last. reached_depth . max ( reached_depth) ;
143- last. encountered_overflow |= encountered_overflow;
144- }
145- }
146-
147137 /// Pops the highest goal from the stack, lazily updating the
148138 /// the next goal in the stack.
149139 ///
@@ -276,37 +266,7 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
276266 return Self :: response_no_constraints ( tcx, input, Certainty :: overflow ( true ) ) ;
277267 } ;
278268
279- // Try to fetch the goal from the global cache.
280- ' global: {
281- let Some ( CacheData { result, proof_tree, reached_depth, encountered_overflow } ) =
282- self . global_cache ( tcx) . get (
283- tcx,
284- input,
285- |cycle_participants| {
286- self . stack . iter ( ) . any ( |entry| cycle_participants. contains ( & entry. input ) )
287- } ,
288- available_depth,
289- )
290- else {
291- break ' global;
292- } ;
293-
294- // If we're building a proof tree and the current cache entry does not
295- // contain a proof tree, we do not use the entry but instead recompute
296- // the goal. We simply overwrite the existing entry once we're done,
297- // caching the proof tree.
298- if !inspect. is_noop ( ) {
299- if let Some ( revisions) = proof_tree {
300- inspect. goal_evaluation_kind (
301- inspect:: WipCanonicalGoalEvaluationKind :: Interned { revisions } ,
302- ) ;
303- } else {
304- break ' global;
305- }
306- }
307-
308- self . on_cache_hit ( reached_depth, encountered_overflow) ;
309- debug ! ( "global cache hit" ) ;
269+ if let Some ( result) = self . lookup_global_cache ( tcx, input, available_depth, inspect) {
310270 return result;
311271 }
312272
@@ -388,7 +348,10 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
388348
389349 // This is for global caching, so we properly track query dependencies.
390350 // Everything that affects the `result` should be performed within this
391- // `with_anon_task` closure.
351+ // `with_anon_task` closure. If computing this goal depends on something
352+ // not tracked by the cache key and from outside of this anon task, it
353+ // must not be added to the global cache. Notably, this is the case for
354+ // trait solver cycles participants.
392355 let ( ( final_entry, result) , dep_node) =
393356 tcx. dep_graph . with_anon_task ( tcx, dep_kinds:: TraitSelect , || {
394357 for _ in 0 ..FIXPOINT_STEP_LIMIT {
@@ -446,6 +409,45 @@ impl<'tcx> SearchGraph<TyCtxt<'tcx>> {
446409
447410 result
448411 }
412+
413+ /// Try to fetch a previously computed result from the global cache,
414+ /// making sure to only do so if it would match the result of reevaluating
415+ /// this goal.
416+ fn lookup_global_cache (
417+ & mut self ,
418+ tcx : TyCtxt < ' tcx > ,
419+ input : CanonicalInput < ' tcx > ,
420+ available_depth : Limit ,
421+ inspect : & mut ProofTreeBuilder < TyCtxt < ' tcx > > ,
422+ ) -> Option < QueryResult < ' tcx > > {
423+ let CacheData { result, proof_tree, additional_depth, encountered_overflow } = self
424+ . global_cache ( tcx)
425+ . get ( tcx, input, self . stack . iter ( ) . map ( |e| e. input ) , available_depth) ?;
426+
427+ // If we're building a proof tree and the current cache entry does not
428+ // contain a proof tree, we do not use the entry but instead recompute
429+ // the goal. We simply overwrite the existing entry once we're done,
430+ // caching the proof tree.
431+ if !inspect. is_noop ( ) {
432+ if let Some ( revisions) = proof_tree {
433+ let kind = inspect:: WipCanonicalGoalEvaluationKind :: Interned { revisions } ;
434+ inspect. goal_evaluation_kind ( kind) ;
435+ } else {
436+ return None ;
437+ }
438+ }
439+
440+ // Update the reached depth of the current goal to make sure
441+ // its state is the same regardless of whether we've used the
442+ // global cache or not.
443+ let reached_depth = self . stack . next_index ( ) . plus ( additional_depth) ;
444+ if let Some ( last) = self . stack . raw . last_mut ( ) {
445+ last. reached_depth = last. reached_depth . max ( reached_depth) ;
446+ last. encountered_overflow |= encountered_overflow;
447+ }
448+
449+ Some ( result)
450+ }
449451}
450452
451453enum StepResult < ' tcx > {
0 commit comments