@@ -1285,6 +1285,62 @@ ConstraintSystem::filterDisjunction(
1285
1285
return SolutionKind::Unsolved;
1286
1286
}
1287
1287
1288
+ // Attempt to find a disjunction of bind constraints where all options
1289
+ // in the disjunction are binding the same type variable.
1290
+ //
1291
+ // Prefer disjunctions where the bound type variable is also the
1292
+ // right-hand side of a conversion constraint, since having a concrete
1293
+ // type that we're converting to can make it possible to split the
1294
+ // constraint system into multiple ones.
1295
+ static Constraint *selectBestBindingDisjunction (
1296
+ ConstraintSystem &cs, SmallVectorImpl<Constraint *> &disjunctions) {
1297
+
1298
+ if (disjunctions.empty ())
1299
+ return nullptr ;
1300
+
1301
+ auto getAsTypeVar = [&cs](Type type) {
1302
+ return cs.simplifyType (type)->getRValueType ()->getAs <TypeVariableType>();
1303
+ };
1304
+
1305
+ Constraint *firstBindDisjunction = nullptr ;
1306
+ for (auto *disjunction : disjunctions) {
1307
+ auto choices = disjunction->getNestedConstraints ();
1308
+ assert (!choices.empty ());
1309
+
1310
+ auto *choice = choices.front ();
1311
+ if (choice->getKind () != ConstraintKind::Bind)
1312
+ continue ;
1313
+
1314
+ // We can judge disjunction based on the single choice
1315
+ // because all of choices (of bind overload set) should
1316
+ // have the same left-hand side.
1317
+ // Only do this for simple type variable bindings, not for
1318
+ // bindings like: ($T1) -> $T2 bind String -> Int
1319
+ auto *typeVar = getAsTypeVar (choice->getFirstType ());
1320
+ if (!typeVar)
1321
+ continue ;
1322
+
1323
+ if (!firstBindDisjunction)
1324
+ firstBindDisjunction = disjunction;
1325
+
1326
+ auto constraints = cs.getConstraintGraph ().gatherConstraints (
1327
+ typeVar, ConstraintGraph::GatheringKind::EquivalenceClass,
1328
+ [](Constraint *constraint) {
1329
+ return constraint->getKind () == ConstraintKind::Conversion;
1330
+ });
1331
+
1332
+ for (auto *constraint : constraints) {
1333
+ if (typeVar == getAsTypeVar (constraint->getSecondType ()))
1334
+ return disjunction;
1335
+ }
1336
+ }
1337
+
1338
+ // If we had any binding disjunctions, return the first of
1339
+ // those. These ensure that we attempt to bind types earlier than
1340
+ // trying the elements of other disjunctions, which can often mean
1341
+ // we fail faster.
1342
+ return firstBindDisjunction;
1343
+ }
1288
1344
1289
1345
std::optional<std::pair<Constraint *, unsigned >>
1290
1346
ConstraintSystem::findConstraintThroughOptionals (
@@ -1760,6 +1816,63 @@ void DisjunctionChoiceProducer::partitionDisjunction(
1760
1816
assert (Ordering.size () == Choices.size ());
1761
1817
}
1762
1818
1819
+ Constraint *ConstraintSystem::selectDisjunction () {
1820
+ SmallVector<Constraint *, 4 > disjunctions;
1821
+
1822
+ collectDisjunctions (disjunctions);
1823
+ if (disjunctions.empty ())
1824
+ return nullptr ;
1825
+
1826
+ optimizeDisjunctions (disjunctions);
1827
+
1828
+ if (auto *disjunction = selectBestBindingDisjunction (*this , disjunctions))
1829
+ return disjunction;
1830
+
1831
+ // Pick the disjunction with the smallest number of favored, then active choices.
1832
+ auto cs = this ;
1833
+ auto minDisjunction = std::min_element (disjunctions.begin (), disjunctions.end (),
1834
+ [&](Constraint *first, Constraint *second) -> bool {
1835
+ unsigned firstActive = first->countActiveNestedConstraints ();
1836
+ unsigned secondActive = second->countActiveNestedConstraints ();
1837
+ unsigned firstFavored = first->countFavoredNestedConstraints ();
1838
+ unsigned secondFavored = second->countFavoredNestedConstraints ();
1839
+
1840
+ if (!isOperatorDisjunction (first) || !isOperatorDisjunction (second))
1841
+ return firstActive < secondActive;
1842
+
1843
+ if (firstFavored == secondFavored) {
1844
+ // Look for additional choices that are "favored"
1845
+ SmallVector<unsigned , 4 > firstExisting;
1846
+ SmallVector<unsigned , 4 > secondExisting;
1847
+
1848
+ existingOperatorBindingsForDisjunction (*cs, first->getNestedConstraints (), firstExisting);
1849
+ firstFavored += firstExisting.size ();
1850
+ existingOperatorBindingsForDisjunction (*cs, second->getNestedConstraints (), secondExisting);
1851
+ secondFavored += secondExisting.size ();
1852
+ }
1853
+
1854
+ // Everything else equal, choose the disjunction with the greatest
1855
+ // number of resolved argument types. The number of resolved argument
1856
+ // types is always zero for disjunctions that don't represent applied
1857
+ // overloads.
1858
+ if (firstFavored == secondFavored) {
1859
+ if (firstActive != secondActive)
1860
+ return firstActive < secondActive;
1861
+
1862
+ return (first->countResolvedArgumentTypes (*this ) > second->countResolvedArgumentTypes (*this ));
1863
+ }
1864
+
1865
+ firstFavored = firstFavored ? firstFavored : firstActive;
1866
+ secondFavored = secondFavored ? secondFavored : secondActive;
1867
+ return firstFavored < secondFavored;
1868
+ });
1869
+
1870
+ if (minDisjunction != disjunctions.end ())
1871
+ return *minDisjunction;
1872
+
1873
+ return nullptr ;
1874
+ }
1875
+
1763
1876
Constraint *ConstraintSystem::selectConjunction () {
1764
1877
SmallVector<Constraint *, 4 > conjunctions;
1765
1878
for (auto &constraint : InactiveConstraints) {
0 commit comments