@@ -35,8 +35,8 @@ use crate::solve::ty::may_use_unstable_feature;
3535use crate :: solve:: {
3636 CanonicalInput , CanonicalResponse , Certainty , ExternalConstraintsData , FIXPOINT_STEP_LIMIT ,
3737 Goal , GoalEvaluation , GoalSource , GoalStalledOn , HasChanged , MaybeCause ,
38- NestedNormalizationGoals , NoSolution , QueryInput , QueryResult , Response , VisibleForLeakCheck ,
39- inspect,
38+ NestedNormalizationGoals , NoSolution , QueryInput , QueryResult , Response , SucceededInErased ,
39+ VisibleForLeakCheck , inspect,
4040} ;
4141
4242mod probe;
@@ -502,6 +502,7 @@ where
502502 ref stalled_vars,
503503 ref sub_roots,
504504 stalled_certainty,
505+ ref previously_succeeded_in_erased,
505506 } ) = stalled_on
506507 else {
507508 return MayMakeProgress ;
@@ -522,7 +523,31 @@ where
522523 // If any opaques changed in the opaque type storage,
523524 // rerunning might make progress so we should rerun.
524525 if self . delegate . opaque_types_storage_num_entries ( ) . needs_reevaluation ( num_opaques) {
525- return MayMakeProgress ;
526+ // Unless this goal previously succeeded in erased mode.
527+ // If the stalled goal successfully evaluated while erasing opaque types,
528+ // and the current state of the opaque type storage is not different in a way that is
529+ // relevant, this stalled goal cannot make any progress and we set this variable to true.
530+ let mut previous_erased_run_is_still_valid = false ;
531+
532+ if let & SucceededInErased :: Yes { accessed_opaques } = previously_succeeded_in_erased {
533+ match self . should_rerun_after_erased_canonicalization (
534+ accessed_opaques,
535+ self . typing_mode ( ) ,
536+ & self . delegate . clone_opaque_types_lookup_table ( ) ,
537+ ) {
538+ RerunDecision :: Yes => { }
539+ RerunDecision :: EagerlyPropagateToParent => {
540+ unreachable ! ( "we never retry stalled queries if the parent was erased" )
541+ }
542+ RerunDecision :: No => {
543+ previous_erased_run_is_still_valid = true ;
544+ }
545+ }
546+ }
547+
548+ if !previous_erased_run_is_still_valid {
549+ return MayMakeProgress ;
550+ }
526551 }
527552
528553 // Otherwise, we can be sure that this stalled goal cannot make any progress
@@ -574,7 +599,7 @@ where
574599 )
575600 . entered ( ) ;
576601
577- let ( result, orig_values, canonical_goal) = ' retry_canonicalize: {
602+ let ( result, orig_values, canonical_goal, succeeded_in_erased ) = ' retry_canonicalize: {
578603 let skip_erased_attempt = if typing_mode. is_coherence ( ) {
579604 true
580605 } else {
@@ -630,11 +655,23 @@ where
630655 match should_rerun {
631656 RerunDecision :: Yes => debug ! ( "rerunning in original typing mode" ) ,
632657 RerunDecision :: No => {
633- break ' retry_canonicalize ( canonical_result, orig_values, canonical_goal) ;
658+ break ' retry_canonicalize (
659+ canonical_result,
660+ orig_values,
661+ canonical_goal,
662+ SucceededInErased :: Yes { accessed_opaques } ,
663+ ) ;
634664 }
635665 RerunDecision :: EagerlyPropagateToParent => {
636666 self . opaque_accesses . update ( accessed_opaques) ?;
637- break ' retry_canonicalize ( canonical_result, orig_values, canonical_goal) ;
667+ break ' retry_canonicalize (
668+ canonical_result,
669+ orig_values,
670+ canonical_goal,
671+ // If we're propagating up, we should never retry the goal.
672+ // That means `No` is fine to return, it doesn't really matter.
673+ SucceededInErased :: No ,
674+ ) ;
638675 }
639676 }
640677 }
@@ -653,7 +690,7 @@ where
653690 "we run without TypingMode::ErasedNotCoherence, so opaques are available, and we don't retry if the outer typing mode is ErasedNotCoherence: {accessed_opaques:?} after {goal:?}"
654691 ) ;
655692
656- ( canonical_result, orig_values, canonical_goal)
693+ ( canonical_result, orig_values, canonical_goal, SucceededInErased :: No )
657694 } ;
658695
659696 debug ! ( ?result) ;
@@ -761,6 +798,7 @@ where
761798 stalled_vars,
762799 sub_roots,
763800 stalled_certainty : certainty,
801+ previously_succeeded_in_erased : succeeded_in_erased,
764802 } )
765803 }
766804 } ,
0 commit comments