@@ -649,93 +649,87 @@ static bool shouldContractEdge(ConstraintKind kind) {
649
649
}
650
650
651
651
bool ConstraintGraph::contractEdges () {
652
- llvm::SetVector<std::pair<TypeVariableType *,
653
- TypeVariableType *>> contractions;
654
-
655
- auto tyvars = getTypeVariables ();
656
- auto didContractEdges = false ;
652
+ SmallVector<Constraint *, 16 > constraints;
653
+ CS.findConstraints (constraints, [](const Constraint &constraint) {
654
+ return shouldContractEdge (constraint.getKind ());
655
+ });
657
656
658
- for (auto tyvar : tyvars) {
659
- SmallVector<Constraint *, 4 > constraints;
660
- gatherConstraints (tyvar, constraints,
661
- ConstraintGraph::GatheringKind::EquivalenceClass);
657
+ bool didContractEdges = false ;
658
+ for (auto *constraint : constraints) {
659
+ auto kind = constraint->getKind ();
662
660
663
- for (auto constraint : constraints) {
664
- auto kind = constraint->getKind ();
665
- // Contract binding edges between type variables.
666
- if (shouldContractEdge (kind)) {
667
- auto t1 = constraint->getFirstType ()->getDesugaredType ();
668
- auto t2 = constraint->getSecondType ()->getDesugaredType ();
661
+ // Contract binding edges between type variables.
662
+ assert (shouldContractEdge (kind));
669
663
670
- auto tyvar1 = t1-> getAs <TypeVariableType> ();
671
- auto tyvar2 = t2-> getAs <TypeVariableType> ();
664
+ auto t1 = constraint-> getFirstType ()-> getDesugaredType ();
665
+ auto t2 = constraint-> getSecondType ()-> getDesugaredType ();
672
666
673
- if (!( tyvar1 && tyvar2))
674
- continue ;
667
+ auto tyvar1 = t1-> getAs <TypeVariableType>();
668
+ auto tyvar2 = t2-> getAs <TypeVariableType>() ;
675
669
676
- auto isParamBindingConstraint = kind == ConstraintKind::BindParam;
677
-
678
- // If the argument is allowed to bind to `inout`, in general,
679
- // it's invalid to contract the edge between argument and parameter,
680
- // but if we can prove that there are no possible bindings
681
- // which result in attempt to bind `inout` type to argument
682
- // type variable, we should go ahead and allow (temporary)
683
- // contraction, because that greatly helps with performance.
684
- // Such action is valid because argument type variable can
685
- // only get its bindings from related overload, which gives
686
- // us enough information to decided on l-valueness.
687
- if (isParamBindingConstraint && tyvar1->getImpl ().canBindToInOut ()) {
688
- bool isNotContractable = true ;
689
- if (auto bindings = CS.getPotentialBindings (tyvar1)) {
690
- for (auto &binding : bindings.Bindings ) {
691
- auto type = binding.BindingType ;
692
- isNotContractable = type.findIf ([&](Type nestedType) -> bool {
693
- if (auto tv = nestedType->getAs <TypeVariableType>()) {
694
- if (!tv->getImpl ().mustBeMaterializable ())
695
- return true ;
696
- }
697
-
698
- return nestedType->is <InOutType>();
699
- });
670
+ if (!(tyvar1 && tyvar2))
671
+ continue ;
700
672
701
- // If there is at least one non-contractable binding, let's
702
- // not risk contracting this edge.
703
- if (isNotContractable)
704
- break ;
673
+ auto isParamBindingConstraint = kind == ConstraintKind::BindParam;
674
+
675
+ // If the argument is allowed to bind to `inout`, in general,
676
+ // it's invalid to contract the edge between argument and parameter,
677
+ // but if we can prove that there are no possible bindings
678
+ // which result in attempt to bind `inout` type to argument
679
+ // type variable, we should go ahead and allow (temporary)
680
+ // contraction, because that greatly helps with performance.
681
+ // Such action is valid because argument type variable can
682
+ // only get its bindings from related overload, which gives
683
+ // us enough information to decided on l-valueness.
684
+ if (isParamBindingConstraint && tyvar1->getImpl ().canBindToInOut ()) {
685
+ bool isNotContractable = true ;
686
+ if (auto bindings = CS.getPotentialBindings (tyvar1)) {
687
+ for (auto &binding : bindings.Bindings ) {
688
+ auto type = binding.BindingType ;
689
+ isNotContractable = type.findIf ([&](Type nestedType) -> bool {
690
+ if (auto tv = nestedType->getAs <TypeVariableType>()) {
691
+ if (!tv->getImpl ().mustBeMaterializable ())
692
+ return true ;
705
693
}
706
- }
707
694
695
+ return nestedType->is <InOutType>();
696
+ });
697
+
698
+ // If there is at least one non-contractable binding, let's
699
+ // not risk contracting this edge.
708
700
if (isNotContractable)
709
- continue ;
701
+ break ;
710
702
}
703
+ }
711
704
712
- auto rep1 = CS.getRepresentative (tyvar1);
713
- auto rep2 = CS.getRepresentative (tyvar2);
714
-
715
- if (((rep1->getImpl ().canBindToLValue () ==
716
- rep2->getImpl ().canBindToLValue ()) ||
717
- // Allow l-value contractions when binding parameter types.
718
- isParamBindingConstraint)) {
719
- if (CS.TC .getLangOpts ().DebugConstraintSolver ) {
720
- auto &log = CS.getASTContext ().TypeCheckerDebug ->getStream ();
721
- if (CS.solverState )
722
- log.indent (CS.solverState ->depth * 2 );
723
-
724
- log << " Contracting constraint " ;
725
- constraint->print (log, &CS.getASTContext ().SourceMgr );
726
- log << " \n " ;
727
- }
728
-
729
- // Merge the edges and remove the constraint.
730
- removeEdge (constraint);
731
- if (rep1 != rep2)
732
- CS.mergeEquivalenceClasses (rep1, rep2, /* updateWorkList*/ false );
733
- didContractEdges = true ;
734
- }
705
+ if (isNotContractable)
706
+ continue ;
707
+ }
708
+
709
+ auto rep1 = CS.getRepresentative (tyvar1);
710
+ auto rep2 = CS.getRepresentative (tyvar2);
711
+
712
+ if (((rep1->getImpl ().canBindToLValue () ==
713
+ rep2->getImpl ().canBindToLValue ()) ||
714
+ // Allow l-value contractions when binding parameter types.
715
+ isParamBindingConstraint)) {
716
+ if (CS.TC .getLangOpts ().DebugConstraintSolver ) {
717
+ auto &log = CS.getASTContext ().TypeCheckerDebug ->getStream ();
718
+ if (CS.solverState )
719
+ log.indent (CS.solverState ->depth * 2 );
720
+
721
+ log << " Contracting constraint " ;
722
+ constraint->print (log, &CS.getASTContext ().SourceMgr );
723
+ log << " \n " ;
735
724
}
725
+
726
+ // Merge the edges and remove the constraint.
727
+ removeEdge (constraint);
728
+ if (rep1 != rep2)
729
+ CS.mergeEquivalenceClasses (rep1, rep2, /* updateWorkList*/ false );
730
+ didContractEdges = true ;
736
731
}
737
732
}
738
-
739
733
return didContractEdges;
740
734
}
741
735
0 commit comments