Skip to content

Commit c7b3b73

Browse files
authored
Merge pull request #85391 from xedin/rdar-164247524
[CSOptimizer] Avoid favoring overloads that mismatch context on async
2 parents 662f8d4 + 513caf2 commit c7b3b73

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "OpenedExistentials.h"
1818
#include "TypeChecker.h"
1919
#include "swift/AST/ConformanceLookup.h"
20+
#include "swift/AST/Decl.h"
2021
#include "swift/AST/ExistentialLayout.h"
2122
#include "swift/AST/Expr.h"
2223
#include "swift/AST/GenericSignature.h"
@@ -777,7 +778,7 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
777778
SmallVector<Constraint *, 2> favoredChoices;
778779
forEachDisjunctionChoice(
779780
cs, disjunction,
780-
[&argumentType, &favoredChoices, &argument](
781+
[&cs, &argumentType, &favoredChoices, &argument](
781782
Constraint *choice, ValueDecl *decl, FunctionType *overloadType) {
782783
if (decl->getAttrs().hasAttribute<DisfavoredOverloadAttr>())
783784
return;
@@ -793,8 +794,15 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
793794
(isa<LiteralExpr>(argument) || isa<BinaryExpr>(argument)))
794795
return;
795796

796-
if (argumentType->isEqual(param.getPlainType()))
797+
if (argumentType->isEqual(param.getPlainType())) {
798+
if (auto *func = dyn_cast<AbstractFunctionDecl>(decl)) {
799+
if (func->isAsyncContext() !=
800+
cs.isAsynchronousContext(choice->getDeclContext()))
801+
return;
802+
}
803+
797804
favoredChoices.push_back(choice);
805+
}
798806
});
799807

800808
return DisjunctionInfoBuilder(/*score=*/favoredChoices.empty() ? 0 : 1,

test/Constraints/old_hack_related_ambiguities.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,3 +383,34 @@ do {
383383
}
384384
}
385385
}
386+
387+
// Calls with single unlabeled arguments shouldn't favor overloads that don't match on async.
388+
do {
389+
struct V {
390+
var data: Int = 0
391+
}
392+
393+
func test(_: Int) -> Int { 42 }
394+
func test(_: Int, v: Int = 42) async -> V? { nil }
395+
396+
func doAsync<T>(_ fn: () async -> T) async -> T { await fn() }
397+
398+
func computeAsync(v: Int) async {
399+
let v1 = await test(v)
400+
if let v1 {
401+
_ = v1.data // Ok
402+
}
403+
404+
let v2 = await doAsync { await test(v) }
405+
if let v2 {
406+
_ = v2.data // Ok
407+
}
408+
409+
_ = await doAsync {
410+
let v = await test(v)
411+
if let v {
412+
_ = v.data // Ok
413+
}
414+
}
415+
}
416+
}

0 commit comments

Comments
 (0)