Skip to content

Commit 4407d7a

Browse files
committed
[CSOptimizer] Avoid favoring overloads that mismatch context on async
This is a fix for the ported "calls with a single unlabeled argument" hack. If overload doesn't match context on async effect, let's not favor it because that is more important than defaulted parameters. Resolves: rdar://164269641
1 parent 4e04842 commit 4407d7a

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"
@@ -768,7 +769,7 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
768769
SmallVector<Constraint *, 2> favoredChoices;
769770
forEachDisjunctionChoice(
770771
cs, disjunction,
771-
[&argumentType, &favoredChoices, &argument](
772+
[&cs, &argumentType, &favoredChoices, &argument](
772773
Constraint *choice, ValueDecl *decl, FunctionType *overloadType) {
773774
if (decl->getAttrs().hasAttribute<DisfavoredOverloadAttr>())
774775
return;
@@ -784,8 +785,15 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
784785
(isa<LiteralExpr>(argument) || isa<BinaryExpr>(argument)))
785786
return;
786787

787-
if (argumentType->isEqual(param.getPlainType()))
788+
if (argumentType->isEqual(param.getPlainType())) {
789+
if (auto *func = dyn_cast<AbstractFunctionDecl>(decl)) {
790+
if (func->isAsyncContext() !=
791+
cs.isAsynchronousContext(choice->getDeclContext()))
792+
return;
793+
}
794+
788795
favoredChoices.push_back(choice);
796+
}
789797
});
790798

791799
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)