@@ -960,6 +960,56 @@ void BindingSet::addLiteralRequirement(Constraint *constraint) {
960
960
Literals.insert ({protocol, std::move (literal)});
961
961
}
962
962
963
+ bool BindingSet::operator ==(const BindingSet &other) {
964
+ if (AdjacentVars != other.AdjacentVars )
965
+ return false ;
966
+
967
+ if (Bindings.size () != other.Bindings .size ())
968
+ return false ;
969
+
970
+ for (auto i : indices (Bindings)) {
971
+ const auto &x = Bindings[i];
972
+ const auto &y = other.Bindings [i];
973
+
974
+ if (x.BindingType .getPointer () != y.BindingType .getPointer () ||
975
+ x.Kind != y.Kind )
976
+ return false ;
977
+ }
978
+
979
+ if (Literals.size () != other.Literals .size ())
980
+ return false ;
981
+
982
+ for (auto pair : Literals) {
983
+ auto found = other.Literals .find (pair.first );
984
+ if (found == other.Literals .end ())
985
+ return false ;
986
+
987
+ const auto &x = pair.second ;
988
+ const auto &y = found->second ;
989
+
990
+ if (x.Source != y.Source ||
991
+ x.DefaultType .getPointer () != y.DefaultType .getPointer () ||
992
+ x.IsDirectRequirement != y.IsDirectRequirement ) {
993
+ return false ;
994
+ }
995
+ }
996
+
997
+ if (Defaults.size () != other.Defaults .size ())
998
+ return false ;
999
+
1000
+ for (auto pair : Defaults) {
1001
+ auto found = other.Defaults .find (pair.first );
1002
+ if (found == other.Defaults .end () ||
1003
+ pair.second != found->second )
1004
+ return false ;
1005
+ }
1006
+
1007
+ if (TransitiveProtocols != other.TransitiveProtocols )
1008
+ return false ;
1009
+
1010
+ return true ;
1011
+ }
1012
+
963
1013
BindingSet::BindingScore BindingSet::formBindingScore (const BindingSet &b) {
964
1014
// If there are no bindings available but this type
965
1015
// variable represents a closure - let's consider it
@@ -980,6 +1030,43 @@ BindingSet::BindingScore BindingSet::formBindingScore(const BindingSet &b) {
980
1030
-numNonDefaultableBindings);
981
1031
}
982
1032
1033
+ bool BindingSet::operator <(const BindingSet &other) {
1034
+ auto xScore = formBindingScore (*this );
1035
+ auto yScore = formBindingScore (other);
1036
+
1037
+ if (xScore < yScore)
1038
+ return true ;
1039
+
1040
+ if (yScore < xScore)
1041
+ return false ;
1042
+
1043
+ auto xDefaults = getNumViableDefaultableBindings ();
1044
+ auto yDefaults = other.getNumViableDefaultableBindings ();
1045
+
1046
+ // If there is a difference in number of default types,
1047
+ // prioritize bindings with fewer of them.
1048
+ if (xDefaults != yDefaults)
1049
+ return xDefaults < yDefaults;
1050
+
1051
+ // If neither type variable is a "hole" let's check whether
1052
+ // there is a subtype relationship between them and prefer
1053
+ // type variable which represents superclass first in order
1054
+ // for "subtype" type variable to attempt more bindings later.
1055
+ // This is required because algorithm can't currently infer
1056
+ // bindings for subtype transitively through superclass ones.
1057
+ if (!(std::get<0 >(xScore) && std::get<0 >(yScore))) {
1058
+ if (Info.isSubtypeOf (other.getTypeVariable ()))
1059
+ return false ;
1060
+
1061
+ if (other.Info .isSubtypeOf (getTypeVariable ()))
1062
+ return true ;
1063
+ }
1064
+
1065
+ // As a last resort, let's check if the bindings are
1066
+ // potentially incomplete, and if so, let's de-prioritize them.
1067
+ return isPotentiallyIncomplete () < other.isPotentiallyIncomplete ();
1068
+ }
1069
+
983
1070
std::optional<BindingSet> ConstraintSystem::determineBestBindings (
984
1071
llvm::function_ref<void (const BindingSet &)> onCandidate) {
985
1072
// Look for potential type variable bindings.
0 commit comments