@@ -40,7 +40,7 @@ pub use global_cache::GlobalCache;
4040pub trait Cx : Copy {
4141 type Input : Debug + Eq + Hash + Copy ;
4242 type Result : Debug + Eq + Hash + Copy ;
43- type AmbiguityInfo : Debug + Eq + Hash + Copy ;
43+ type AmbiguityKind : Debug + Eq + Hash + Copy ;
4444
4545 type DepNodeIndex ;
4646 type Tracked < T : Debug + Clone > : Debug ;
@@ -92,19 +92,16 @@ pub trait Delegate: Sized {
9292 cx : Self :: Cx ,
9393 input : <Self :: Cx as Cx >:: Input ,
9494 ) -> <Self :: Cx as Cx >:: Result ;
95+
96+ const FIXPOINT_OVERFLOW_AMBIGUITY_KIND : <Self :: Cx as Cx >:: AmbiguityKind ;
9597 fn fixpoint_overflow_result (
9698 cx : Self :: Cx ,
9799 input : <Self :: Cx as Cx >:: Input ,
98100 ) -> <Self :: Cx as Cx >:: Result ;
99101
100102 fn is_ambiguous_result (
101103 result : <Self :: Cx as Cx >:: Result ,
102- ) -> Option < <Self :: Cx as Cx >:: AmbiguityInfo > ;
103- fn propagate_ambiguity (
104- cx : Self :: Cx ,
105- for_input : <Self :: Cx as Cx >:: Input ,
106- ambiguity_info : <Self :: Cx as Cx >:: AmbiguityInfo ,
107- ) -> <Self :: Cx as Cx >:: Result ;
104+ ) -> Option < <Self :: Cx as Cx >:: AmbiguityKind > ;
108105
109106 fn compute_goal (
110107 search_graph : & mut SearchGraph < Self > ,
@@ -929,8 +926,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
929926#[ derive_where( Debug ; X : Cx ) ]
930927enum RebaseReason < X : Cx > {
931928 NoCycleUsages ,
932- Ambiguity ( X :: AmbiguityInfo ) ,
933- Overflow ,
929+ Ambiguity ( X :: AmbiguityKind ) ,
934930 /// We've actually reached a fixpoint.
935931 ///
936932 /// This either happens in the first evaluation step for the cycle head.
@@ -961,10 +957,9 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
961957 /// cache entries to also be ambiguous. This causes some undesirable ambiguity for nested
962958 /// goals whose result doesn't actually depend on this cycle head, but that's acceptable
963959 /// to me.
964- #[ instrument( level = "trace" , skip( self , cx ) ) ]
960+ #[ instrument( level = "trace" , skip( self ) ) ]
965961 fn rebase_provisional_cache_entries (
966962 & mut self ,
967- cx : X ,
968963 stack_entry : & StackEntry < X > ,
969964 rebase_reason : RebaseReason < X > ,
970965 ) {
@@ -1039,18 +1034,22 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
10391034 }
10401035
10411036 // The provisional cache entry does depend on the provisional result
1042- // of the popped cycle head. We need to mutate the result of our
1043- // provisional cache entry in case we did not reach a fixpoint .
1037+ // of the popped cycle head. In case we didn't actually reach a fixpoint,
1038+ // we must not keep potentially incorrect provisional cache entries around .
10441039 match rebase_reason {
10451040 // If the cycle head does not actually depend on itself, then
10461041 // the provisional result used by the provisional cache entry
10471042 // is not actually equal to the final provisional result. We
10481043 // need to discard the provisional cache entry in this case.
10491044 RebaseReason :: NoCycleUsages => return false ,
1050- RebaseReason :: Ambiguity ( info) => {
1051- * result = D :: propagate_ambiguity ( cx, input, info) ;
1045+ // If we avoid rerunning a goal due to ambiguity, we only keep provisional
1046+ // results which depend on that cycle head if these are already ambiguous
1047+ // themselves.
1048+ RebaseReason :: Ambiguity ( kind) => {
1049+ if !D :: is_ambiguous_result ( * result) . is_some_and ( |k| k == kind) {
1050+ return false ;
1051+ }
10521052 }
1053- RebaseReason :: Overflow => * result = D :: fixpoint_overflow_result ( cx, input) ,
10541053 RebaseReason :: ReachedFixpoint ( None ) => { }
10551054 RebaseReason :: ReachedFixpoint ( Some ( path_kind) ) => {
10561055 if !popped_head. usages . is_single ( path_kind) {
@@ -1352,17 +1351,12 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
13521351 // final result is equal to the initial response for that case.
13531352 if let Ok ( fixpoint) = self . reached_fixpoint ( & stack_entry, usages, result) {
13541353 self . rebase_provisional_cache_entries (
1355- cx,
13561354 & stack_entry,
13571355 RebaseReason :: ReachedFixpoint ( fixpoint) ,
13581356 ) ;
13591357 return EvaluationResult :: finalize ( stack_entry, encountered_overflow, result) ;
13601358 } else if usages. is_empty ( ) {
1361- self . rebase_provisional_cache_entries (
1362- cx,
1363- & stack_entry,
1364- RebaseReason :: NoCycleUsages ,
1365- ) ;
1359+ self . rebase_provisional_cache_entries ( & stack_entry, RebaseReason :: NoCycleUsages ) ;
13661360 return EvaluationResult :: finalize ( stack_entry, encountered_overflow, result) ;
13671361 }
13681362
@@ -1371,19 +1365,15 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
13711365 // response in the next iteration in this case. These changes would
13721366 // likely either be caused by incompleteness or can change the maybe
13731367 // cause from ambiguity to overflow. Returning ambiguity always
1374- // preserves soundness and completeness even if the goal is be known
1375- // to succeed or fail.
1368+ // preserves soundness and completeness even if the goal could
1369+ // otherwise succeed or fail.
13761370 //
13771371 // This prevents exponential blowup affecting multiple major crates.
13781372 // As we only get to this branch if we haven't yet reached a fixpoint,
13791373 // we also taint all provisional cache entries which depend on the
13801374 // current goal.
1381- if let Some ( info) = D :: is_ambiguous_result ( result) {
1382- self . rebase_provisional_cache_entries (
1383- cx,
1384- & stack_entry,
1385- RebaseReason :: Ambiguity ( info) ,
1386- ) ;
1375+ if let Some ( kind) = D :: is_ambiguous_result ( result) {
1376+ self . rebase_provisional_cache_entries ( & stack_entry, RebaseReason :: Ambiguity ( kind) ) ;
13871377 return EvaluationResult :: finalize ( stack_entry, encountered_overflow, result) ;
13881378 } ;
13891379
@@ -1393,7 +1383,10 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D, X> {
13931383 if i >= D :: FIXPOINT_STEP_LIMIT {
13941384 debug ! ( "canonical cycle overflow" ) ;
13951385 let result = D :: fixpoint_overflow_result ( cx, input) ;
1396- self . rebase_provisional_cache_entries ( cx, & stack_entry, RebaseReason :: Overflow ) ;
1386+ self . rebase_provisional_cache_entries (
1387+ & stack_entry,
1388+ RebaseReason :: Ambiguity ( D :: FIXPOINT_OVERFLOW_AMBIGUITY_KIND ) ,
1389+ ) ;
13971390 return EvaluationResult :: finalize ( stack_entry, encountered_overflow, result) ;
13981391 }
13991392
0 commit comments