@@ -1488,6 +1488,31 @@ ConstraintSystem::TypeMatchResult constraints::matchCallArguments(
1488
1488
}
1489
1489
}
1490
1490
1491
+ // Detect that there is sync -> async mismatch early on for
1492
+ // closure argument to avoid re-checking calls if there was
1493
+ // an overload choice with synchronous parameter of the same
1494
+ // shape e.g.
1495
+ //
1496
+ // func test(_: () -> Void) -> MyStruct {}
1497
+ // func test(_: () async -> Void) -> MyStruct {}
1498
+ //
1499
+ // test({ ... }).<member>...
1500
+ //
1501
+ // Synchronous overload is always better in this case so there
1502
+ // is no need to re-check follow-up `<member>`s and better
1503
+ // to short-circuit this path early.
1504
+ if (auto *fnType = paramTy->getAs <FunctionType>()) {
1505
+ if (fnType->isAsync ()) {
1506
+ auto *typeVar = argTy->getAs <TypeVariableType>();
1507
+ if (typeVar && typeVar->getImpl ().isClosureType ()) {
1508
+ auto *locator = typeVar->getImpl ().getLocator ();
1509
+ auto *closure = castToExpr<ClosureExpr>(locator->getAnchor ());
1510
+ if (!cs.getClosureType (closure)->isAsync ())
1511
+ cs.increaseScore (SK_SyncInAsync);
1512
+ }
1513
+ }
1514
+ }
1515
+
1491
1516
cs.addConstraint (
1492
1517
subKind, argTy, paramTy,
1493
1518
matchingAutoClosureResult
@@ -2037,7 +2062,20 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
2037
2062
return getTypeMatchFailure (locator);
2038
2063
}
2039
2064
2040
- increaseScore (SK_SyncInAsync);
2065
+ bool forClosureInArgumentPosition = false ;
2066
+ if (auto last = locator.last ()) {
2067
+ forClosureInArgumentPosition =
2068
+ last->is <LocatorPathElt::ApplyArgToParam>() &&
2069
+ isa<ClosureExpr>(locator.trySimplifyToExpr ());
2070
+ }
2071
+
2072
+ // Since it's possible to infer `async` from the body of a
2073
+ // closure, score for sync -> async mismatch is increased
2074
+ // while solver is matching arguments to parameters to
2075
+ // indicate than solution with such a mismatch is always
2076
+ // worse than one with synchronous functions on both sides.
2077
+ if (!forClosureInArgumentPosition)
2078
+ increaseScore (SK_SyncInAsync);
2041
2079
}
2042
2080
2043
2081
// A @Sendable function can be a subtype of a non-@Sendable function.
0 commit comments