@@ -129,16 +129,6 @@ impl<'tcx> SearchGraph<'tcx> {
129
129
self . mode
130
130
}
131
131
132
- /// Update the stack and reached depths on cache hits.
133
- #[ instrument( level = "debug" , skip( self ) ) ]
134
- fn on_cache_hit ( & mut self , additional_depth : usize , encountered_overflow : bool ) {
135
- let reached_depth = self . stack . next_index ( ) . plus ( additional_depth) ;
136
- if let Some ( last) = self . stack . raw . last_mut ( ) {
137
- last. reached_depth = last. reached_depth . max ( reached_depth) ;
138
- last. encountered_overflow |= encountered_overflow;
139
- }
140
- }
141
-
142
132
/// Pops the highest goal from the stack, lazily updating the
143
133
/// the next goal in the stack.
144
134
///
@@ -266,36 +256,7 @@ impl<'tcx> SearchGraph<'tcx> {
266
256
return Self :: response_no_constraints ( tcx, input, Certainty :: overflow ( true ) ) ;
267
257
} ;
268
258
269
- // Try to fetch the goal from the global cache.
270
- ' global: {
271
- let Some ( CacheData { result, proof_tree, reached_depth, encountered_overflow } ) =
272
- self . global_cache ( tcx) . get (
273
- tcx,
274
- input,
275
- |cycle_participants| {
276
- self . stack . iter ( ) . any ( |entry| cycle_participants. contains ( & entry. input ) )
277
- } ,
278
- available_depth,
279
- )
280
- else {
281
- break ' global;
282
- } ;
283
-
284
- // If we're building a proof tree and the current cache entry does not
285
- // contain a proof tree, we do not use the entry but instead recompute
286
- // the goal. We simply overwrite the existing entry once we're done,
287
- // caching the proof tree.
288
- if !inspect. is_noop ( ) {
289
- if let Some ( revisions) = proof_tree {
290
- inspect. goal_evaluation_kind (
291
- inspect:: WipCanonicalGoalEvaluationKind :: Interned { revisions } ,
292
- ) ;
293
- } else {
294
- break ' global;
295
- }
296
- }
297
-
298
- self . on_cache_hit ( reached_depth, encountered_overflow) ;
259
+ if let Some ( result) = self . lookup_global_cache ( tcx, input, available_depth, inspect) {
299
260
return result;
300
261
}
301
262
@@ -376,7 +337,10 @@ impl<'tcx> SearchGraph<'tcx> {
376
337
377
338
// This is for global caching, so we properly track query dependencies.
378
339
// Everything that affects the `result` should be performed within this
379
- // `with_anon_task` closure.
340
+ // `with_anon_task` closure. If computing this goal depends on something
341
+ // not tracked by the cache key and from outside of this anon task, it
342
+ // must not be added to the global cache. Notably, this is the case for
343
+ // trait solver cycles participants.
380
344
let ( ( final_entry, result) , dep_node) =
381
345
tcx. dep_graph . with_anon_task ( tcx, dep_kinds:: TraitSelect , || {
382
346
for _ in 0 ..FIXPOINT_STEP_LIMIT {
@@ -434,6 +398,45 @@ impl<'tcx> SearchGraph<'tcx> {
434
398
435
399
result
436
400
}
401
+
402
+ /// Try to fetch a previously computed result from the global cache,
403
+ /// making sure to only do so if it would match the result of reevaluating
404
+ /// this goal.
405
+ fn lookup_global_cache (
406
+ & mut self ,
407
+ tcx : TyCtxt < ' tcx > ,
408
+ input : CanonicalInput < ' tcx > ,
409
+ available_depth : Limit ,
410
+ inspect : & mut ProofTreeBuilder < ' tcx > ,
411
+ ) -> Option < QueryResult < ' tcx > > {
412
+ let CacheData { result, proof_tree, additional_depth, encountered_overflow } = self
413
+ . global_cache ( tcx)
414
+ . get ( tcx, input, self . stack . iter ( ) . map ( |e| e. input ) , available_depth) ?;
415
+
416
+ // If we're building a proof tree and the current cache entry does not
417
+ // contain a proof tree, we do not use the entry but instead recompute
418
+ // the goal. We simply overwrite the existing entry once we're done,
419
+ // caching the proof tree.
420
+ if !inspect. is_noop ( ) {
421
+ if let Some ( revisions) = proof_tree {
422
+ let kind = inspect:: WipCanonicalGoalEvaluationKind :: Interned { revisions } ;
423
+ inspect. goal_evaluation_kind ( kind) ;
424
+ } else {
425
+ return None ;
426
+ }
427
+ }
428
+
429
+ // Update the reached depth of the current goal to make sure
430
+ // its state is the same regardless of whether we've used the
431
+ // global cache or not.
432
+ let reached_depth = self . stack . next_index ( ) . plus ( additional_depth) ;
433
+ if let Some ( last) = self . stack . raw . last_mut ( ) {
434
+ last. reached_depth = last. reached_depth . max ( reached_depth) ;
435
+ last. encountered_overflow |= encountered_overflow;
436
+ }
437
+
438
+ Some ( result)
439
+ }
437
440
}
438
441
439
442
enum StepResult < ' tcx > {
0 commit comments