@@ -22,8 +22,9 @@ use crate::delegate::SolverDelegate;
2222use  crate :: solve:: inspect:: { self ,  ProofTreeBuilder } ; 
2323use  crate :: solve:: search_graph:: SearchGraph ; 
2424use  crate :: solve:: { 
25-     CanonicalInput ,  Certainty ,  FIXPOINT_STEP_LIMIT ,  Goal ,  GoalEvaluationKind ,  GoalSource , 
26-     HasChanged ,  NestedNormalizationGoals ,  NoSolution ,  QueryInput ,  QueryResult , 
25+     CanonicalInput ,  Certainty ,  FIXPOINT_STEP_LIMIT ,  Goal ,  GoalEvaluation ,  GoalEvaluationKind , 
26+     GoalSource ,  GoalStalledOn ,  HasChanged ,  NestedNormalizationGoals ,  NoSolution ,  QueryInput , 
27+     QueryResult , 
2728} ; 
2829
2930pub ( super )  mod  canonical; 
@@ -115,7 +116,7 @@ where
115116
116117    pub ( super )  search_graph :  & ' a  mut  SearchGraph < D > , 
117118
118-     nested_goals :  Vec < ( GoalSource ,  Goal < I ,  I :: Predicate > ) > , 
119+     nested_goals :  Vec < ( GoalSource ,  Goal < I ,  I :: Predicate > ,   Option < GoalStalledOn < I > > ) > , 
119120
120121    pub ( super )  origin_span :  I :: Span , 
121122
@@ -147,8 +148,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
147148        goal :  Goal < Self :: Interner ,  <Self :: Interner  as  Interner >:: Predicate > , 
148149        generate_proof_tree :  GenerateProofTree , 
149150        span :  <Self :: Interner  as  Interner >:: Span , 
151+         stalled_on :  Option < GoalStalledOn < Self :: Interner > > , 
150152    )  -> ( 
151-         Result < ( HasChanged ,   Certainty ) ,  NoSolution > , 
153+         Result < GoalEvaluation < Self :: Interner > ,  NoSolution > , 
152154        Option < inspect:: GoalEvaluation < Self :: Interner > > , 
153155    ) ; 
154156
@@ -171,8 +173,12 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
171173        & self , 
172174        goal :  Goal < Self :: Interner ,  <Self :: Interner  as  Interner >:: Predicate > , 
173175        generate_proof_tree :  GenerateProofTree , 
176+         stalled_on :  Option < GoalStalledOn < Self :: Interner > > , 
174177    )  -> ( 
175-         Result < ( NestedNormalizationGoals < Self :: Interner > ,  HasChanged ,  Certainty ) ,  NoSolution > , 
178+         Result < 
179+             ( NestedNormalizationGoals < Self :: Interner > ,  GoalEvaluation < Self :: Interner > ) , 
180+             NoSolution , 
181+         > , 
176182        Option < inspect:: GoalEvaluation < Self :: Interner > > , 
177183    ) ; 
178184} 
@@ -188,9 +194,10 @@ where
188194        goal :  Goal < I ,  I :: Predicate > , 
189195        generate_proof_tree :  GenerateProofTree , 
190196        span :  I :: Span , 
191-     )  -> ( Result < ( HasChanged ,  Certainty ) ,  NoSolution > ,  Option < inspect:: GoalEvaluation < I > > )  { 
197+         stalled_on :  Option < GoalStalledOn < I > > , 
198+     )  -> ( Result < GoalEvaluation < I > ,  NoSolution > ,  Option < inspect:: GoalEvaluation < I > > )  { 
192199        EvalCtxt :: enter_root ( self ,  self . cx ( ) . recursion_limit ( ) ,  generate_proof_tree,  span,  |ecx| { 
193-             ecx. evaluate_goal ( GoalEvaluationKind :: Root ,  GoalSource :: Misc ,  goal) 
200+             ecx. evaluate_goal ( GoalEvaluationKind :: Root ,  GoalSource :: Misc ,  goal,  stalled_on ) 
194201        } ) 
195202    } 
196203
@@ -201,7 +208,7 @@ where
201208    )  -> bool  { 
202209        self . probe ( || { 
203210            EvalCtxt :: enter_root ( self ,  root_depth,  GenerateProofTree :: No ,  I :: Span :: dummy ( ) ,  |ecx| { 
204-                 ecx. evaluate_goal ( GoalEvaluationKind :: Root ,  GoalSource :: Misc ,  goal) 
211+                 ecx. evaluate_goal ( GoalEvaluationKind :: Root ,  GoalSource :: Misc ,  goal,   None ) 
205212            } ) 
206213            . 0 
207214        } ) 
@@ -213,16 +220,19 @@ where
213220        & self , 
214221        goal :  Goal < I ,  I :: Predicate > , 
215222        generate_proof_tree :  GenerateProofTree , 
223+         stalled_on :  Option < GoalStalledOn < I > > , 
216224    )  -> ( 
217-         Result < ( NestedNormalizationGoals < I > ,  HasChanged ,   Certainty ) ,  NoSolution > , 
225+         Result < ( NestedNormalizationGoals < I > ,  GoalEvaluation < I > ) ,  NoSolution > , 
218226        Option < inspect:: GoalEvaluation < I > > , 
219227    )  { 
220228        EvalCtxt :: enter_root ( 
221229            self , 
222230            self . cx ( ) . recursion_limit ( ) , 
223231            generate_proof_tree, 
224232            I :: Span :: dummy ( ) , 
225-             |ecx| ecx. evaluate_goal_raw ( GoalEvaluationKind :: Root ,  GoalSource :: Misc ,  goal) , 
233+             |ecx| { 
234+                 ecx. evaluate_goal_raw ( GoalEvaluationKind :: Root ,  GoalSource :: Misc ,  goal,  stalled_on) 
235+             } , 
226236        ) 
227237    } 
228238} 
@@ -447,11 +457,12 @@ where
447457        goal_evaluation_kind :  GoalEvaluationKind , 
448458        source :  GoalSource , 
449459        goal :  Goal < I ,  I :: Predicate > , 
450-     )  -> Result < ( HasChanged ,  Certainty ) ,  NoSolution >  { 
451-         let  ( normalization_nested_goals,  has_changed,  certainty)  =
452-             self . evaluate_goal_raw ( goal_evaluation_kind,  source,  goal) ?; 
460+         stalled_on :  Option < GoalStalledOn < I > > , 
461+     )  -> Result < GoalEvaluation < I > ,  NoSolution >  { 
462+         let  ( normalization_nested_goals,  goal_evaluation)  =
463+             self . evaluate_goal_raw ( goal_evaluation_kind,  source,  goal,  stalled_on) ?; 
453464        assert ! ( normalization_nested_goals. is_empty( ) ) ; 
454-         Ok ( ( has_changed ,  certainty ) ) 
465+         Ok ( goal_evaluation ) 
455466    } 
456467
457468    /// Recursively evaluates `goal`, returning the nested goals in case 
@@ -466,7 +477,29 @@ where
466477        goal_evaluation_kind :  GoalEvaluationKind , 
467478        source :  GoalSource , 
468479        goal :  Goal < I ,  I :: Predicate > , 
469-     )  -> Result < ( NestedNormalizationGoals < I > ,  HasChanged ,  Certainty ) ,  NoSolution >  { 
480+         stalled_on :  Option < GoalStalledOn < I > > , 
481+     )  -> Result < ( NestedNormalizationGoals < I > ,  GoalEvaluation < I > ) ,  NoSolution >  { 
482+         // If we have run this goal before, and it was stalled, check that any of the goal's 
483+         // args have changed. Otherwise, we don't need to re-run the goal because it'll remain 
484+         // stalled, since it'll canonicalize the same way and evaluation is pure. 
485+         if  let  Some ( stalled_on)  = stalled_on { 
486+             if  !stalled_on. stalled_vars . iter ( ) . any ( |value| self . delegate . is_changed_arg ( * value) ) 
487+                 && !self 
488+                     . delegate 
489+                     . opaque_types_storage_num_entries ( ) 
490+                     . needs_reevaluation ( stalled_on. num_opaques ) 
491+             { 
492+                 return  Ok ( ( 
493+                     NestedNormalizationGoals :: empty ( ) , 
494+                     GoalEvaluation  { 
495+                         certainty :  Certainty :: Maybe ( stalled_on. stalled_cause ) , 
496+                         has_changed :  HasChanged :: No , 
497+                         stalled_on :  Some ( stalled_on) , 
498+                     } , 
499+                 ) ) ; 
500+             } 
501+         } 
502+ 
470503        let  ( orig_values,  canonical_goal)  = self . canonicalize_goal ( goal) ; 
471504        let  mut  goal_evaluation =
472505            self . inspect . new_goal_evaluation ( goal,  & orig_values,  goal_evaluation_kind) ; 
@@ -489,7 +522,7 @@ where
489522            if  !has_only_region_constraints ( response)  {  HasChanged :: Yes  }  else  {  HasChanged :: No  } ; 
490523
491524        let  ( normalization_nested_goals,  certainty)  =
492-             self . instantiate_and_apply_query_response ( goal. param_env ,  orig_values,  response) ; 
525+             self . instantiate_and_apply_query_response ( goal. param_env ,  & orig_values,  response) ; 
493526        self . inspect . goal_evaluation ( goal_evaluation) ; 
494527
495528        // FIXME: We previously had an assert here that checked that recomputing 
@@ -502,7 +535,42 @@ where
502535        // Once we have decided on how to handle trait-system-refactor-initiative#75, 
503536        // we should re-add an assert here. 
504537
505-         Ok ( ( normalization_nested_goals,  has_changed,  certainty) ) 
538+         let  stalled_on = match  certainty { 
539+             Certainty :: Yes  => None , 
540+             Certainty :: Maybe ( stalled_cause)  => match  has_changed { 
541+                 // FIXME: We could recompute a *new* set of stalled variables by walking 
542+                 // through the orig values, resolving, and computing the root vars of anything 
543+                 // that is not resolved. Only when *these* have changed is it meaningful 
544+                 // to recompute this goal. 
545+                 HasChanged :: Yes  => None , 
546+                 HasChanged :: No  => { 
547+                     // Remove the unconstrained RHS arg, which is expected to have changed. 
548+                     let  mut  stalled_vars = orig_values; 
549+                     if  let  Some ( normalizes_to)  = goal. predicate . as_normalizes_to ( )  { 
550+                         let  normalizes_to = normalizes_to. skip_binder ( ) ; 
551+                         let  rhs_arg:  I :: GenericArg  = normalizes_to. term . into ( ) ; 
552+                         let  idx = stalled_vars
553+                             . iter ( ) 
554+                             . rposition ( |arg| * arg == rhs_arg) 
555+                             . expect ( "expected unconstrained arg" ) ; 
556+                         stalled_vars. swap_remove ( idx) ; 
557+                     } 
558+ 
559+                     Some ( GoalStalledOn  { 
560+                         num_opaques :  canonical_goal
561+                             . canonical 
562+                             . value 
563+                             . predefined_opaques_in_body 
564+                             . opaque_types 
565+                             . len ( ) , 
566+                         stalled_vars, 
567+                         stalled_cause, 
568+                     } ) 
569+                 } 
570+             } , 
571+         } ; 
572+ 
573+         Ok ( ( normalization_nested_goals,  GoalEvaluation  {  certainty,  has_changed,  stalled_on } ) ) 
506574    } 
507575
508576    fn  compute_goal ( & mut  self ,  goal :  Goal < I ,  I :: Predicate > )  -> QueryResult < I >  { 
@@ -602,7 +670,7 @@ where
602670        let  cx = self . cx ( ) ; 
603671        // If this loop did not result in any progress, what's our final certainty. 
604672        let  mut  unchanged_certainty = Some ( Certainty :: Yes ) ; 
605-         for  ( source,  goal)  in  mem:: take ( & mut  self . nested_goals )  { 
673+         for  ( source,  goal,  stalled_on )  in  mem:: take ( & mut  self . nested_goals )  { 
606674            if  let  Some ( has_changed)  = self . delegate . compute_goal_fast_path ( goal,  self . origin_span ) 
607675            { 
608676                if  matches ! ( has_changed,  HasChanged :: Yes )  { 
@@ -630,11 +698,18 @@ where
630698                let  unconstrained_goal =
631699                    goal. with ( cx,  ty:: NormalizesTo  {  alias :  pred. alias ,  term :  unconstrained_rhs } ) ; 
632700
633-                 let  ( NestedNormalizationGoals ( nested_goals) ,  _,  certainty)  =
634-                     self . evaluate_goal_raw ( GoalEvaluationKind :: Nested ,  source,  unconstrained_goal) ?; 
701+                 let  ( 
702+                     NestedNormalizationGoals ( nested_goals) , 
703+                     GoalEvaluation  {  certainty,  stalled_on,  has_changed :  _ } , 
704+                 )  = self . evaluate_goal_raw ( 
705+                     GoalEvaluationKind :: Nested , 
706+                     source, 
707+                     unconstrained_goal, 
708+                     stalled_on, 
709+                 ) ?; 
635710                // Add the nested goals from normalization to our own nested goals. 
636711                trace ! ( ?nested_goals) ; 
637-                 self . nested_goals . extend ( nested_goals) ; 
712+                 self . nested_goals . extend ( nested_goals. into_iter ( ) . map ( | ( s ,  g ) |  ( s ,  g ,   None ) ) ) ; 
638713
639714                // Finally, equate the goal's RHS with the unconstrained var. 
640715                // 
@@ -660,6 +735,8 @@ where
660735                // looking at the "has changed" return from evaluate_goal, 
661736                // because we expect the `unconstrained_rhs` part of the predicate 
662737                // to have changed -- that means we actually normalized successfully! 
738+                 // FIXME: Do we need to eagerly resolve here? Or should we check 
739+                 // if the cache key has any changed vars? 
663740                let  with_resolved_vars = self . resolve_vars_if_possible ( goal) ; 
664741                if  pred. alias  != goal. predicate . as_normalizes_to ( ) . unwrap ( ) . skip_binder ( ) . alias  { 
665742                    unchanged_certainty = None ; 
@@ -668,21 +745,21 @@ where
668745                match  certainty { 
669746                    Certainty :: Yes  => { } 
670747                    Certainty :: Maybe ( _)  => { 
671-                         self . nested_goals . push ( ( source,  with_resolved_vars) ) ; 
748+                         self . nested_goals . push ( ( source,  with_resolved_vars,  stalled_on ) ) ; 
672749                        unchanged_certainty = unchanged_certainty. map ( |c| c. and ( certainty) ) ; 
673750                    } 
674751                } 
675752            }  else  { 
676-                 let  ( has_changed,  certainty )  =
677-                     self . evaluate_goal ( GoalEvaluationKind :: Nested ,  source,  goal) ?; 
753+                 let  GoalEvaluation   {  certainty ,   has_changed,  stalled_on  }  =
754+                     self . evaluate_goal ( GoalEvaluationKind :: Nested ,  source,  goal,  stalled_on ) ?; 
678755                if  has_changed == HasChanged :: Yes  { 
679756                    unchanged_certainty = None ; 
680757                } 
681758
682759                match  certainty { 
683760                    Certainty :: Yes  => { } 
684761                    Certainty :: Maybe ( _)  => { 
685-                         self . nested_goals . push ( ( source,  goal) ) ; 
762+                         self . nested_goals . push ( ( source,  goal,  stalled_on ) ) ; 
686763                        unchanged_certainty = unchanged_certainty. map ( |c| c. and ( certainty) ) ; 
687764                    } 
688765                } 
@@ -706,7 +783,7 @@ where
706783        goal. predicate  =
707784            goal. predicate . fold_with ( & mut  ReplaceAliasWithInfer :: new ( self ,  source,  goal. param_env ) ) ; 
708785        self . inspect . add_goal ( self . delegate ,  self . max_input_universe ,  source,  goal) ; 
709-         self . nested_goals . push ( ( source,  goal) ) ; 
786+         self . nested_goals . push ( ( source,  goal,   None ) ) ; 
710787    } 
711788
712789    #[ instrument( level = "trace" ,  skip( self ,  goals) ) ]  
0 commit comments