@@ -493,61 +493,6 @@ fn initialize_environment<'a>(
493493
494494impl < ' a , Ans : LookupAnswer > AnswersSolver < ' a , Ans > {
495495 fn compute_variance_env ( & self , class : & Class ) -> VarianceEnv {
496- fn fixpoint < ' a , Ans : LookupAnswer > (
497- solver : & AnswersSolver < ' a , Ans > ,
498- mut env : VarianceEnv ,
499- ) -> VarianceEnv {
500- let mut changed = true ;
501-
502- while changed {
503- changed = false ;
504- let mut new_environment: VarianceEnv = SmallMap :: new ( ) ;
505-
506- for ( my_class, params) in env. iter ( ) {
507- let mut new_params = params. clone ( ) ;
508-
509- let mut on_var =
510- |name : & Name ,
511- variance : Variance ,
512- has_inferred : bool ,
513- _: PreInferenceVariance | {
514- if let Some ( old_status) = new_params. get_mut ( name) {
515- let new_inferred_variance =
516- variance. union ( old_status. inferred_variance ) ;
517- // Mark as inferred if:
518- // 1. It was already marked as inferred, OR
519- // 2. The caller says this is an injective (reliable) constraint, OR
520- // 3. The inferred variance is no longer Bivariant (we found a constraint)
521- // Case 3 fixes self-referential types where `has_inferred` is always false
522- // but we still discover variance constraints through the fixpoint iteration.
523- let new_has_variance_inferred = old_status. has_variance_inferred
524- || has_inferred
525- || new_inferred_variance != Variance :: Bivariant ;
526- if new_inferred_variance != old_status. inferred_variance
527- || new_has_variance_inferred != old_status. has_variance_inferred
528- {
529- old_status. inferred_variance = new_inferred_variance;
530- old_status. has_variance_inferred = new_has_variance_inferred;
531- changed = true ;
532- }
533- }
534- } ;
535- let mut on_edge = |c : & Class | env. get ( c) . cloned ( ) . unwrap_or_default ( ) ;
536- on_class (
537- my_class,
538- solver. heap ,
539- & mut on_edge,
540- & mut on_var,
541- & |c| solver. get_base_types_for_class ( c) ,
542- & |c| solver. get_class_field_map ( c) ,
543- ) ;
544- new_environment. insert ( my_class. dupe ( ) , new_params) ;
545- }
546- env = new_environment;
547- }
548- env
549- }
550-
551496 let mut environment = VarianceEnv :: new ( ) ;
552497 let initial_inference_map_for_class =
553498 initial_inference_map ( self . get_class_tparams ( class) . as_vec ( ) ) ;
@@ -566,8 +511,58 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
566511 & |c| self . get_class_field_map ( c) ,
567512 & |c| self . get_class_tparams ( c) ,
568513 ) ;
569- fixpoint ( self , environment)
514+ self . fixpoint ( environment)
515+ }
516+ }
517+
518+ fn fixpoint ( & self , mut env : VarianceEnv ) -> VarianceEnv {
519+ let mut changed = true ;
520+
521+ while changed {
522+ changed = false ;
523+ let mut new_environment: VarianceEnv = SmallMap :: new ( ) ;
524+
525+ for ( my_class, params) in env. iter ( ) {
526+ let mut new_params = params. clone ( ) ;
527+
528+ let mut on_var = |name : & Name ,
529+ variance : Variance ,
530+ has_inferred : bool ,
531+ _: PreInferenceVariance | {
532+ if let Some ( old_status) = new_params. get_mut ( name) {
533+ let new_inferred_variance = variance. union ( old_status. inferred_variance ) ;
534+ // Mark as inferred if:
535+ // 1. It was already marked as inferred, OR
536+ // 2. The caller says this is an injective (reliable) constraint, OR
537+ // 3. The inferred variance is no longer Bivariant (we found a constraint)
538+ // Case 3 fixes self-referential types where `has_inferred` is always false
539+ // but we still discover variance constraints through the fixpoint iteration.
540+ let new_has_variance_inferred = old_status. has_variance_inferred
541+ || has_inferred
542+ || new_inferred_variance != Variance :: Bivariant ;
543+ if new_inferred_variance != old_status. inferred_variance
544+ || new_has_variance_inferred != old_status. has_variance_inferred
545+ {
546+ old_status. inferred_variance = new_inferred_variance;
547+ old_status. has_variance_inferred = new_has_variance_inferred;
548+ changed = true ;
549+ }
550+ }
551+ } ;
552+ let mut on_edge = |c : & Class | env. get ( c) . cloned ( ) . unwrap_or_default ( ) ;
553+ on_class (
554+ my_class,
555+ self . heap ,
556+ & mut on_edge,
557+ & mut on_var,
558+ & |c| self . get_base_types_for_class ( c) ,
559+ & |c| self . get_class_field_map ( c) ,
560+ ) ;
561+ new_environment. insert ( my_class. dupe ( ) , new_params) ;
562+ }
563+ env = new_environment;
570564 }
565+ env
571566 }
572567
573568 /// Compute variance for a class, optionally checking for violations.
0 commit comments