mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include "OpenedExistentials.h"
|
||||
#include "TypeChecker.h"
|
||||
#include "swift/AST/ConformanceLookup.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/ExistentialLayout.h"
|
||||
#include "swift/AST/Expr.h"
|
||||
#include "swift/AST/GenericSignature.h"
|
||||
@@ -768,7 +769,7 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
|
||||
SmallVector<Constraint *, 2> favoredChoices;
|
||||
forEachDisjunctionChoice(
|
||||
cs, disjunction,
|
||||
[&argumentType, &favoredChoices, &argument](
|
||||
[&cs, &argumentType, &favoredChoices, &argument](
|
||||
Constraint *choice, ValueDecl *decl, FunctionType *overloadType) {
|
||||
if (decl->getAttrs().hasAttribute<DisfavoredOverloadAttr>())
|
||||
return;
|
||||
@@ -784,8 +785,15 @@ static std::optional<DisjunctionInfo> preserveFavoringOfUnlabeledUnaryArgument(
|
||||
(isa<LiteralExpr>(argument) || isa<BinaryExpr>(argument)))
|
||||
return;
|
||||
|
||||
if (argumentType->isEqual(param.getPlainType()))
|
||||
if (argumentType->isEqual(param.getPlainType())) {
|
||||
if (auto *func = dyn_cast<AbstractFunctionDecl>(decl)) {
|
||||
if (func->isAsyncContext() !=
|
||||
cs.isAsynchronousContext(choice->getDeclContext()))
|
||||
return;
|
||||
}
|
||||
|
||||
favoredChoices.push_back(choice);
|
||||
}
|
||||
});
|
||||
|
||||
return DisjunctionInfoBuilder(/*score=*/favoredChoices.empty() ? 0 : 1,
|
||||
|
||||
@@ -383,3 +383,34 @@ do {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calls with single unlabeled arguments shouldn't favor overloads that don't match on async.
|
||||
do {
|
||||
struct V {
|
||||
var data: Int = 0
|
||||
}
|
||||
|
||||
func test(_: Int) -> Int { 42 }
|
||||
func test(_: Int, v: Int = 42) async -> V? { nil }
|
||||
|
||||
func doAsync<T>(_ fn: () async -> T) async -> T { await fn() }
|
||||
|
||||
func computeAsync(v: Int) async {
|
||||
let v1 = await test(v)
|
||||
if let v1 {
|
||||
_ = v1.data // Ok
|
||||
}
|
||||
|
||||
let v2 = await doAsync { await test(v) }
|
||||
if let v2 {
|
||||
_ = v2.data // Ok
|
||||
}
|
||||
|
||||
_ = await doAsync {
|
||||
let v = await test(v)
|
||||
if let v {
|
||||
_ = v.data // Ok
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user