Skip to content

Commit a4dd60c

Browse files
authored
Merge pull request swiftlang#36828 from slavapestov/reasync-ranking-fix
Sema: Don't score a solution higher if there's a sync-vs-async mismatch with a 'reasync' function
2 parents f539d33 + 3994c46 commit a4dd60c

File tree

3 files changed

+36
-5
lines changed

3 files changed

+36
-5
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -627,8 +627,8 @@ bool CompareDeclSpecializationRequest::evaluate(
627627
// If they both have trailing closures, compare those separately.
628628
bool compareTrailingClosureParamsSeparately = false;
629629
if (numParams1 > 0 && numParams2 > 0 &&
630-
params1.back().getOldType()->is<AnyFunctionType>() &&
631-
params2.back().getOldType()->is<AnyFunctionType>()) {
630+
params1.back().getParameterType()->is<AnyFunctionType>() &&
631+
params2.back().getParameterType()->is<AnyFunctionType>()) {
632632
compareTrailingClosureParamsSeparately = true;
633633
}
634634

@@ -1132,8 +1132,8 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
11321132
auto params = fnTy->getParams();
11331133
assert(params.size() == 2);
11341134

1135-
auto param1 = params[0].getOldType();
1136-
auto param2 = params[1].getOldType()->castTo<AnyFunctionType>();
1135+
auto param1 = params[0].getParameterType();
1136+
auto param2 = params[1].getParameterType()->castTo<AnyFunctionType>();
11371137

11381138
assert(param1->getOptionalObjectType());
11391139
assert(params[1].isAutoClosure());

lib/Sema/ConstraintSystem.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2890,7 +2890,8 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
28902890
// If we're choosing an asynchronous declaration within a synchronous
28912891
// context, or vice-versa, increase the async/async mismatch score.
28922892
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
2893-
if (func->isAsyncContext() != isAsynchronousContext(useDC)) {
2893+
if (!func->hasPolymorphicEffect(EffectKind::Async) &&
2894+
func->isAsyncContext() != isAsynchronousContext(useDC)) {
28942895
increaseScore(
28952896
func->isAsyncContext() ? SK_AsyncInSyncMismatch : SK_SyncInAsync);
28962897
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
2+
3+
// We don't want 'reasync' overloads to have a higher score in the
4+
// case of a sync vs reasync mismatch the way 'async' overloads do,
5+
// since this would change solver performance characteristics when
6+
// using the reasync '&&', '||' and '??' operators.
7+
8+
func asyncOverload(_: () async -> (), _: Int) async {}
9+
func asyncOverload(_: () -> (), _: String) {}
10+
11+
func referencesAsyncOverload() {
12+
_ = asyncOverload // we prefer the sync overload
13+
}
14+
15+
func referencesAsyncOverloadAsync() async {
16+
_ = asyncOverload // we prefer the async overload
17+
}
18+
19+
func reasyncOverload(_: () async -> (), _: Int) reasync {} // expected-note {{found this candidate}}
20+
func reasyncOverload(_: () -> (), _: String) {} // expected-note {{found this candidate}}
21+
22+
func referencesReasyncOverload() {
23+
_ = reasyncOverload // expected-error {{ambiguous use of 'reasyncOverload'}}
24+
}
25+
26+
func referencesReasyncOverloadAsync() async {
27+
// we prefer the async overload because the sync overload scores higher
28+
// due to a sync-vs-async mismatch.
29+
_ = reasyncOverload
30+
}

0 commit comments

Comments
 (0)