Description
Description
Hello,
SE-0296 contains those paragraphs in its Overloading and overload resolution section:
[...] we propose an overload-resolution rule to select the appropriate function based on the context of the call. Given a call, overload resolution prefers non-async functions within a synchronous context (because such contexts cannot contain a call to an async function). Furthermore, overload resolution prefers async functions within an asynchronous context (because such contexts should avoid stepping out of the asynchronous model into blocking APIs).
This rule is crucially important, because when a library ships an async overload of a sync function, it may well be with the intent of avoiding the grave problems that happen when the cooperative thread pool is blocked by the sync overload. The language must respect the intended design of SE-0296, and the care put by API authors into helping their users write correct programs. See this very interesting forum thread for a longer discussion.
The reason for this issue is that the overload resolution is not correctly implemented, and the compiler mistakenly allows sync calls in asynchronous contexts.
Reproduction
struct Runner {
func run() { }
func run() async { }
}
func testSync() {
// 👍 sync overload chosen
Runner().run()
}
func testAsync() async {
// 👍 compiler error: expression is 'async' but is not marked with 'await'
// Runner().run()
await Runner().run()
}
func testTask() {
Task {
// ❌ sync overload wrongly chosen. No error and no warning.
Runner().run()
}
}
Expected behavior
The testTask
function does not compile, and the compiler complains with "expression is 'async' but is not marked with 'await'"
Environment
Problem exists in Swift 5.10, and still exists in Xcode 16 beta:
swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0
swift-driver version: 1.109.2 Apple Swift version 6.0 (swiftlang-6.0.0.3.300 clang-1600.0.20.10)
Target: arm64-apple-macosx14.0
Additional information
@_disfavoredOverload
does not help. I don't know any workaround that would have the compiler correctly identify the incorrect use of the sync overload in an async context.