Skip to content

Commit 4325cf4

Browse files
committed
Ensure that async/synchronous overloading works in implicit-async closures.
When we are within a closure that is not required to be asynchronous (i.e., it has no `await` in it), make sure that we prefer synchronous functions to asynchronous ones, even if this closure will later be converted to `async` and the constraint system knows that. Fixes rdar://88692889.
1 parent f417630 commit 4325cf4

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2724,13 +2724,11 @@ bool ConstraintSystem::isAsynchronousContext(DeclContext *dc) {
27242724
if (auto func = dyn_cast<AbstractFunctionDecl>(dc))
27252725
return func->isAsyncContext();
27262726

2727-
if (auto abstractClosure = dyn_cast<AbstractClosureExpr>(dc)) {
2728-
if (Type type = GetClosureType{*this}(abstractClosure)) {
2729-
if (auto fnType = type->getAs<AnyFunctionType>())
2730-
return fnType->isAsync();
2731-
}
2732-
2733-
return abstractClosure->isBodyAsync();
2727+
if (auto closure = dyn_cast<ClosureExpr>(dc)) {
2728+
return evaluateOrDefault(
2729+
getASTContext().evaluator,
2730+
ClosureEffectsRequest{const_cast<ClosureExpr *>(closure)},
2731+
FunctionType::ExtInfo()).isAsync();
27342732
}
27352733

27362734
return false;

test/Constraints/async.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,20 @@ func testAsyncWithConversions() async {
163163
// expected-error@-1:7{{expression is 'async' but is not marked with 'await'}}{{7-7=await }}
164164
// expected-note@-2:7{{call is 'async'}}
165165
}
166+
167+
// rdar://88692889 - make sure overload resolution cues off the presence of
168+
// 'await' in the body to determine whether to prefer async functions, not
169+
// whether the closure is in a context where it will be converted to async.
170+
@available(SwiftStdlib 5.1, *)
171+
struct OverloadInImplicitAsyncClosure {
172+
init(int: Int) async throws {
173+
let task = Task { () -> Self in
174+
let result = try Self(int: int)
175+
return result
176+
}
177+
178+
self = try await task.value
179+
}
180+
181+
init(int: Int) throws { }
182+
}

0 commit comments

Comments
 (0)