@@ -741,39 +741,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
741741 if reached_depth >= stack. depth {
742742 debug ! ( ?result, "CACHE MISS" ) ;
743743 self . insert_evaluation_cache ( param_env, fresh_trait_pred, dep_node, result) ;
744-
745- stack. cache ( ) . on_completion (
746- stack. dfn ,
747- |fresh_trait_pred, provisional_result, provisional_dep_node| {
748- // Create a new `DepNode` that has dependencies on:
749- // * The `DepNode` for the original evaluation that resulted in a provisional cache
750- // entry being crated
751- // * The `DepNode` for the *current* evaluation, which resulted in us completing
752- // provisional caches entries and inserting them into the evaluation cache
753- //
754- // This ensures that when a query reads this entry from the evaluation cache,
755- // it will end up (transitively) depending on all of the incr-comp dependencies
756- // created during the evaluation of this trait. For example, evaluating a trait
757- // will usually require us to invoke `type_of(field_def_id)` to determine the
758- // constituent types, and we want any queries reading from this evaluation
759- // cache entry to end up with a transitive `type_of(field_def_id`)` dependency.
760- //
761- // By using `in_task`, we're also creating an edge from the *current* query
762- // to the newly-created `combined_dep_node`. This is probably redundant,
763- // but it's better to add too many dep graph edges than to add too few
764- // dep graph edges.
765- let ( ( ) , combined_dep_node) = self . in_task ( |this| {
766- this. tcx ( ) . dep_graph . read_index ( provisional_dep_node) ;
767- this. tcx ( ) . dep_graph . read_index ( dep_node) ;
768- } ) ;
769- self . insert_evaluation_cache (
770- param_env,
771- fresh_trait_pred,
772- combined_dep_node,
773- provisional_result. max ( result) ,
774- ) ;
775- } ,
776- ) ;
744+ stack. cache ( ) . on_completion ( stack. dfn ) ;
777745 } else {
778746 debug ! ( ?result, "PROVISIONAL" ) ;
779747 debug ! (
@@ -782,13 +750,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
782750 fresh_trait_pred, stack. depth, reached_depth,
783751 ) ;
784752
785- stack. cache ( ) . insert_provisional (
786- stack. dfn ,
787- reached_depth,
788- fresh_trait_pred,
789- result,
790- dep_node,
791- ) ;
753+ stack. cache ( ) . insert_provisional ( stack. dfn , reached_depth, fresh_trait_pred, result) ;
792754 }
793755
794756 Ok ( result)
@@ -2531,11 +2493,6 @@ struct ProvisionalEvaluation {
25312493 from_dfn : usize ,
25322494 reached_depth : usize ,
25332495 result : EvaluationResult ,
2534- /// The `DepNodeIndex` created for the `evaluate_stack` call for this provisional
2535- /// evaluation. When we create an entry in the evaluation cache using this provisional
2536- /// cache entry (see `on_completion`), we use this `dep_node` to ensure that future reads from
2537- /// the cache will have all of the necessary incr comp dependencies tracked.
2538- dep_node : DepNodeIndex ,
25392496}
25402497
25412498impl < ' tcx > Default for ProvisionalEvaluationCache < ' tcx > {
@@ -2578,7 +2535,6 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
25782535 reached_depth : usize ,
25792536 fresh_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
25802537 result : EvaluationResult ,
2581- dep_node : DepNodeIndex ,
25822538 ) {
25832539 debug ! ( ?from_dfn, ?fresh_trait_pred, ?result, "insert_provisional" ) ;
25842540
@@ -2604,10 +2560,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
26042560 }
26052561 }
26062562
2607- map. insert (
2608- fresh_trait_pred,
2609- ProvisionalEvaluation { from_dfn, reached_depth, result, dep_node } ,
2610- ) ;
2563+ map. insert ( fresh_trait_pred, ProvisionalEvaluation { from_dfn, reached_depth, result } ) ;
26112564 }
26122565
26132566 /// Invoked when the node with dfn `dfn` does not get a successful
@@ -2633,8 +2586,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
26332586 /// Invoked when the node at depth `depth` completed without
26342587 /// depending on anything higher in the stack (if that completion
26352588 /// was a failure, then `on_failure` should have been invoked
2636- /// already). The callback `op` will be invoked for each
2637- /// provisional entry that we can now confirm.
2589+ /// already).
26382590 ///
26392591 /// Note that we may still have provisional cache items remaining
26402592 /// in the cache when this is done. For example, if there is a
@@ -2655,19 +2607,26 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
26552607 /// would be 2, representing the C node, and hence we would
26562608 /// remove the result for D, which has DFN 3, but not the results for
26572609 /// A and B, which have DFNs 0 and 1 respectively).
2658- fn on_completion (
2659- & self ,
2660- dfn : usize ,
2661- mut op : impl FnMut ( ty:: PolyTraitPredicate < ' tcx > , EvaluationResult , DepNodeIndex ) ,
2662- ) {
2610+ ///
2611+ /// Note that we *do not* attempt to cache these cycle participants
2612+ /// in the evaluation cache. Doing so would require carefully computing
2613+ /// the correct `DepNode` to store in the cache entry:
2614+ /// cycle participants may implicitly depend on query results
2615+ /// related to other participants in the cycle, due to our logic
2616+ /// which examines the evaluation stack.
2617+ ///
2618+ /// We used to try to perform this caching,
2619+ /// but it lead to multiple incremental compilation ICEs
2620+ /// (see #92987 and #96319), and was very hard to understand.
2621+ /// Fortunately, removing the caching didn't seem to
2622+ /// have a performance impact in practice.
2623+ fn on_completion ( & self , dfn : usize ) {
26632624 debug ! ( ?dfn, "on_completion" ) ;
26642625
26652626 for ( fresh_trait_pred, eval) in
26662627 self . map . borrow_mut ( ) . drain_filter ( |_k, eval| eval. from_dfn >= dfn)
26672628 {
26682629 debug ! ( ?fresh_trait_pred, ?eval, "on_completion" ) ;
2669-
2670- op ( fresh_trait_pred, eval. result , eval. dep_node ) ;
26712630 }
26722631 }
26732632}
0 commit comments