@@ -1376,6 +1376,64 @@ ConstraintSystem::getTypeOfMemberReference(
1376
1376
return { openedType, type };
1377
1377
}
1378
1378
1379
+ // Performance hack: if there are two generic overloads, and one is
1380
+ // more specialized than the other, prefer the more-specialized one.
1381
+ static void tryOptimizeGenericDisjunction (ConstraintSystem &cs,
1382
+ ArrayRef<OverloadChoice> choices,
1383
+ OverloadChoice *&favoredChoice) {
1384
+ if (favoredChoice || choices.size () != 2 )
1385
+ return ;
1386
+
1387
+ const auto &choiceA = choices[0 ];
1388
+ const auto &choiceB = choices[1 ];
1389
+
1390
+ if (!choiceA.isDecl () || !choiceB.isDecl ())
1391
+ return ;
1392
+
1393
+ auto isViable = [](ValueDecl *decl) -> bool {
1394
+ assert (decl);
1395
+
1396
+ auto *AFD = dyn_cast<AbstractFunctionDecl>(decl);
1397
+ if (!AFD || !AFD->isGeneric ())
1398
+ return false ;
1399
+
1400
+ auto funcType = AFD->getInterfaceType ();
1401
+ auto hasAny = funcType.findIf ([](Type type) -> bool {
1402
+ if (auto objType = type->getOptionalObjectType ())
1403
+ return objType->isAny ();
1404
+
1405
+ return type->isAny ();
1406
+ });
1407
+
1408
+ // If function declaration references `Any` or `Any?` type
1409
+ // let's not attempt it, because it's unclear
1410
+ // without solving which overload is going to be better.
1411
+ return !hasAny;
1412
+ };
1413
+
1414
+ auto *declA = choiceA.getDecl ();
1415
+ auto *declB = choiceB.getDecl ();
1416
+
1417
+ if (!isViable (declA) || !isViable (declB))
1418
+ return ;
1419
+
1420
+ auto &TC = cs.TC ;
1421
+ auto *DC = cs.DC ;
1422
+
1423
+ switch (TC.compareDeclarations (DC, declA, declB)) {
1424
+ case Comparison::Better:
1425
+ favoredChoice = const_cast <OverloadChoice *>(&choiceA);
1426
+ break ;
1427
+
1428
+ case Comparison::Worse:
1429
+ favoredChoice = const_cast <OverloadChoice *>(&choiceB);
1430
+ break ;
1431
+
1432
+ case Comparison::Unordered:
1433
+ break ;
1434
+ }
1435
+ }
1436
+
1379
1437
void ConstraintSystem::addOverloadSet (Type boundType,
1380
1438
ArrayRef<OverloadChoice> choices,
1381
1439
DeclContext *useDC,
@@ -1389,28 +1447,7 @@ void ConstraintSystem::addOverloadSet(Type boundType,
1389
1447
return ;
1390
1448
}
1391
1449
1392
- // Performance hack: if there are two generic overloads, and one is
1393
- // more specialized than the other, prefer the more-specialized one.
1394
- if (!favoredChoice && choices.size () == 2 &&
1395
- choices[0 ].isDecl () && choices[1 ].isDecl () &&
1396
- isa<AbstractFunctionDecl>(choices[0 ].getDecl ()) &&
1397
- cast<AbstractFunctionDecl>(choices[0 ].getDecl ())->isGeneric () &&
1398
- isa<AbstractFunctionDecl>(choices[1 ].getDecl ()) &&
1399
- cast<AbstractFunctionDecl>(choices[1 ].getDecl ())->isGeneric ()) {
1400
- switch (TC.compareDeclarations (DC, choices[0 ].getDecl (),
1401
- choices[1 ].getDecl ())) {
1402
- case Comparison::Better:
1403
- favoredChoice = const_cast <OverloadChoice *>(&choices[0 ]);
1404
- break ;
1405
-
1406
- case Comparison::Worse:
1407
- favoredChoice = const_cast <OverloadChoice *>(&choices[1 ]);
1408
- break ;
1409
-
1410
- case Comparison::Unordered:
1411
- break ;
1412
- }
1413
- }
1450
+ tryOptimizeGenericDisjunction (*this , choices, favoredChoice);
1414
1451
1415
1452
SmallVector<Constraint *, 4 > overloads;
1416
1453
0 commit comments