@@ -1369,37 +1369,12 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1,
1369
1369
static unsigned
1370
1370
assessRequirementFailureImpact (ConstraintSystem &cs, Type requirementType,
1371
1371
ConstraintLocatorBuilder locator) {
1372
+ assert (requirementType);
1373
+
1374
+ unsigned impact = 1 ;
1372
1375
auto *anchor = locator.getAnchor ();
1373
1376
if (!anchor)
1374
- return 1 ;
1375
-
1376
- if (requirementType && cs.simplifyType (requirementType)->isStdlibType ()) {
1377
- if (auto last = locator.last ()) {
1378
- if (auto requirement = last->getAs <LocatorPathElt::AnyRequirement>()) {
1379
- auto kind = requirement->getRequirementKind ();
1380
- if (kind == RequirementKind::Conformance)
1381
- return 3 ;
1382
- }
1383
- }
1384
- }
1385
-
1386
- // If this requirement is associated with an overload choice let's
1387
- // tie impact to how many times this requirement type is mentioned.
1388
- if (auto *ODRE = dyn_cast<OverloadedDeclRefExpr>(anchor)) {
1389
- if (!(requirementType && requirementType->is <TypeVariableType>()))
1390
- return 1 ;
1391
-
1392
- unsigned choiceImpact = 0 ;
1393
- if (auto choice = cs.findSelectedOverloadFor (ODRE)) {
1394
- auto *typeVar = requirementType->castTo <TypeVariableType>();
1395
- choice->openedType .visit ([&](Type type) {
1396
- if (type->isEqual (typeVar))
1397
- ++choiceImpact;
1398
- });
1399
- }
1400
-
1401
- return choiceImpact == 0 ? 1 : choiceImpact;
1402
- }
1377
+ return impact;
1403
1378
1404
1379
// If this requirement is associated with a member reference and it
1405
1380
// was possible to check it before overload choice is bound, that means
@@ -1417,13 +1392,53 @@ assessRequirementFailureImpact(ConstraintSystem &cs, Type requirementType,
1417
1392
// fix for same-type requirement higher impact vs. requirement associated
1418
1393
// with method itself e.g. `func foo<U>() -> U where U : P {}` because
1419
1394
// `foo` is accessible from any `S` regardless of what `T` is.
1395
+ //
1396
+ // Don't add this impact with the others, as we want to keep it consistent
1397
+ // across requirement failures to present the user with a choice.
1420
1398
if (isa<UnresolvedDotExpr>(anchor) || isa<UnresolvedMemberExpr>(anchor)) {
1421
1399
auto *calleeLoc = cs.getCalleeLocator (cs.getConstraintLocator (locator));
1422
1400
if (!cs.findSelectedOverloadFor (calleeLoc))
1423
1401
return 10 ;
1424
1402
}
1425
1403
1426
- return 1 ;
1404
+ // Increase the impact of a conformance fix for a standard library type,
1405
+ // as it's unlikely to be a good suggestion. Also do the same for the builtin
1406
+ // compiler types Any and AnyObject, which cannot conform to protocols.
1407
+ // FIXME: We ought not to have the is<TypeVariableType>() condition here, but
1408
+ // removing it currently regresses the diagnostic for the test case for
1409
+ // rdar://60727310. Once we better handle the separation of conformance fixes
1410
+ // from argument mismatches in cases like SR-12438, we should be able to
1411
+ // remove it from the condition.
1412
+ auto resolvedTy = cs.simplifyType (requirementType);
1413
+ if ((requirementType->is <TypeVariableType>() && resolvedTy->isStdlibType ()) ||
1414
+ resolvedTy->isAny () || resolvedTy->isAnyObject ()) {
1415
+ if (auto last = locator.last ()) {
1416
+ if (auto requirement = last->getAs <LocatorPathElt::AnyRequirement>()) {
1417
+ auto kind = requirement->getRequirementKind ();
1418
+ if (kind == RequirementKind::Conformance)
1419
+ impact += 2 ;
1420
+ }
1421
+ }
1422
+ }
1423
+
1424
+ // If this requirement is associated with an overload choice let's
1425
+ // tie impact to how many times this requirement type is mentioned.
1426
+ if (auto *ODRE = dyn_cast<OverloadedDeclRefExpr>(anchor)) {
1427
+ if (auto *typeVar = requirementType->getAs <TypeVariableType>()) {
1428
+ unsigned choiceImpact = 0 ;
1429
+ if (auto choice = cs.findSelectedOverloadFor (ODRE)) {
1430
+ choice->openedType .visit ([&](Type type) {
1431
+ if (type->isEqual (typeVar))
1432
+ ++choiceImpact;
1433
+ });
1434
+ }
1435
+ // If the type is used multiple times in the signature, increase the
1436
+ // impact for every additional use.
1437
+ if (choiceImpact > 1 )
1438
+ impact += choiceImpact - 1 ;
1439
+ }
1440
+ }
1441
+ return impact;
1427
1442
}
1428
1443
1429
1444
// / Attempt to fix missing arguments by introducing type variables
@@ -5072,6 +5087,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
5072
5087
ConstraintKind kind,
5073
5088
ConstraintLocatorBuilder locator,
5074
5089
TypeMatchOptions flags) {
5090
+ const auto rawType = type;
5075
5091
auto *typeVar = type->getAs <TypeVariableType>();
5076
5092
5077
5093
// Dig out the fixed type to which this type refers.
@@ -5243,7 +5259,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
5243
5259
5244
5260
if (auto *fix =
5245
5261
fixRequirementFailure (*this , type, protocolTy, anchor, path)) {
5246
- auto impact = assessRequirementFailureImpact (*this , typeVar , locator);
5262
+ auto impact = assessRequirementFailureImpact (*this , rawType , locator);
5247
5263
if (!recordFix (fix, impact)) {
5248
5264
// Record this conformance requirement as "fixed".
5249
5265
recordFixedRequirement (type, RequirementKind::Conformance,
0 commit comments