@@ -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
116117pub ( 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
120121pub ( super ) origin_span : I :: Span ,
121122
@@ -147,8 +148,9 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
147148goal : Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > ,
148149generate_proof_tree : GenerateProofTree ,
149150span : <Self :: Interner as Interner >:: Span ,
151+ stalled_on : Option < GoalStalledOn < Self :: Interner > > ,
150152) -> (
151- Result < ( HasChanged , Certainty ) , NoSolution > ,
153+ Result < GoalEvaluation < Self :: Interner > , NoSolution > ,
152154Option < inspect:: GoalEvaluation < Self :: Interner > > ,
153155) ;
154156
@@ -171,8 +173,12 @@ pub trait SolverDelegateEvalExt: SolverDelegate {
171173& self ,
172174goal : Goal < Self :: Interner , <Self :: Interner as Interner >:: Predicate > ,
173175generate_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+ > ,
176182Option < inspect:: GoalEvaluation < Self :: Interner > > ,
177183) ;
178184}
@@ -188,9 +194,10 @@ where
188194goal : Goal < I , I :: Predicate > ,
189195generate_proof_tree : GenerateProofTree ,
190196span : 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 > > ) {
192199EvalCtxt :: 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 {
202209self . probe ( || {
203210EvalCtxt :: 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 ,
214221goal : Goal < I , I :: Predicate > ,
215222generate_proof_tree : GenerateProofTree ,
223+ stalled_on : Option < GoalStalledOn < I > > ,
216224) -> (
217- Result < ( NestedNormalizationGoals < I > , HasChanged , Certainty ) , NoSolution > ,
225+ Result < ( NestedNormalizationGoals < I > , GoalEvaluation < I > ) , NoSolution > ,
218226Option < inspect:: GoalEvaluation < I > > ,
219227) {
220228EvalCtxt :: enter_root (
221229self ,
222230self . cx ( ) . recursion_limit ( ) ,
223231 generate_proof_tree,
224232I :: 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
447457goal_evaluation_kind : GoalEvaluationKind ,
448458source : GoalSource ,
449459goal : 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) ?;
453464assert ! ( 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
466477goal_evaluation_kind : GoalEvaluationKind ,
467478source : GoalSource ,
468479goal : 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+
470503let ( orig_values, canonical_goal) = self . canonicalize_goal ( goal) ;
471504let mut goal_evaluation =
472505self . inspect . new_goal_evaluation ( goal, & orig_values, goal_evaluation_kind) ;
@@ -489,7 +522,7 @@ where
489522if !has_only_region_constraints ( response) { HasChanged :: Yes } else { HasChanged :: No } ;
490523
491524let ( 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) ;
493526self . 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
508576fn compute_goal ( & mut self , goal : Goal < I , I :: Predicate > ) -> QueryResult < I > {
@@ -602,7 +670,7 @@ where
602670let cx = self . cx ( ) ;
603671// If this loop did not result in any progress, what's our final certainty.
604672let 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 ) {
606674if let Some ( has_changed) = self . delegate . compute_goal_fast_path ( goal, self . origin_span )
607675{
608676if matches ! ( has_changed, HasChanged :: Yes ) {
@@ -630,11 +698,18 @@ where
630698let 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.
636711trace ! ( ?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?
663740let with_resolved_vars = self . resolve_vars_if_possible ( goal) ;
664741if pred. alias != goal. predicate . as_normalizes_to ( ) . unwrap ( ) . skip_binder ( ) . alias {
665742 unchanged_certainty = None ;
@@ -668,21 +745,21 @@ where
668745match certainty {
669746Certainty :: Yes => { }
670747Certainty :: 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 ) ?;
678755if has_changed == HasChanged :: Yes {
679756 unchanged_certainty = None ;
680757}
681758
682759match certainty {
683760Certainty :: Yes => { }
684761Certainty :: 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 ) ) ;
708785self . 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