@@ -1486,6 +1486,64 @@ ConstraintSystem::getTypeOfMemberReference(
1486
1486
return { openedType, type };
1487
1487
}
1488
1488
1489
+ // Performance hack: if there are two generic overloads, and one is
1490
+ // more specialized than the other, prefer the more-specialized one.
1491
+ static void tryOptimizeGenericDisjunction (ConstraintSystem &cs,
1492
+ ArrayRef<OverloadChoice> choices,
1493
+ OverloadChoice *&favoredChoice) {
1494
+ if (favoredChoice || choices.size () != 2 )
1495
+ return ;
1496
+
1497
+ const auto &choiceA = choices[0 ];
1498
+ const auto &choiceB = choices[1 ];
1499
+
1500
+ if (!choiceA.isDecl () || !choiceB.isDecl ())
1501
+ return ;
1502
+
1503
+ auto isViable = [](ValueDecl *decl) -> bool {
1504
+ assert (decl);
1505
+
1506
+ auto *AFD = dyn_cast<AbstractFunctionDecl>(decl);
1507
+ if (!AFD || !AFD->isGeneric ())
1508
+ return false ;
1509
+
1510
+ auto funcType = AFD->getInterfaceType ();
1511
+ auto hasAnyOrOptional = funcType.findIf ([](Type type) -> bool {
1512
+ if (auto objType = type->getOptionalObjectType ())
1513
+ return true ;
1514
+
1515
+ return type->isAny ();
1516
+ });
1517
+
1518
+ // If function declaration references `Any` or `Any?` type
1519
+ // let's not attempt it, because it's unclear
1520
+ // without solving which overload is going to be better.
1521
+ return !hasAnyOrOptional;
1522
+ };
1523
+
1524
+ auto *declA = choiceA.getDecl ();
1525
+ auto *declB = choiceB.getDecl ();
1526
+
1527
+ if (!isViable (declA) || !isViable (declB))
1528
+ return ;
1529
+
1530
+ auto &TC = cs.TC ;
1531
+ auto *DC = cs.DC ;
1532
+
1533
+ switch (TC.compareDeclarations (DC, declA, declB)) {
1534
+ case Comparison::Better:
1535
+ favoredChoice = const_cast <OverloadChoice *>(&choiceA);
1536
+ break ;
1537
+
1538
+ case Comparison::Worse:
1539
+ favoredChoice = const_cast <OverloadChoice *>(&choiceB);
1540
+ break ;
1541
+
1542
+ case Comparison::Unordered:
1543
+ break ;
1544
+ }
1545
+ }
1546
+
1489
1547
void ConstraintSystem::addOverloadSet (Type boundType,
1490
1548
ArrayRef<OverloadChoice> choices,
1491
1549
DeclContext *useDC,
@@ -1500,6 +1558,8 @@ void ConstraintSystem::addOverloadSet(Type boundType,
1500
1558
return ;
1501
1559
}
1502
1560
1561
+ tryOptimizeGenericDisjunction (*this , choices, favoredChoice);
1562
+
1503
1563
SmallVector<Constraint *, 4 > overloads;
1504
1564
1505
1565
// As we do for other favored constraints, if a favored overload has been
0 commit comments