-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Description
When using withoutActuallyEscaping
together with withCheckedContinuation
in the following codes, I still occasionally get the runtime error “closure argument was escaped in withoutActuallyEscaping block“. I have also tried using a ClosureHolder in order to use unowned capture in the closure, but unfortunately, the same error still occurs.
This error does not always happen and is easier to be triggered when the run
function in the following codes multiple times in parallel.
Reproduction
func run<R: Sendable>(_ block: @Sendable () -> R) async -> R {
return await withoutActuallyEscaping(block) { localBlock in
return await withCheckedContinuation { continuation in
DispatchQueue.global().async {
continuation.resume(returning: localBlock())
}
}
}
}
await withTaskGroup { group in
for i in 0 ..< 500 {
group.addTask {
await run {
print(i)
}
}
}
}
The version with ClosureHolder
final class ClosureHolder<R>: Sendable {
let closure: (@Sendable () -> R)
init(closure: @Sendable @escaping () -> R) {
self.closure = closure
}
}
func run<R: Sendable>(_ block: @Sendable () -> R) async -> R {
return await withoutActuallyEscaping(block) { localBlock in
let holder = ClosureHolder(closure: localBlock)
return await withCheckedContinuation { [unowned holder] continuation in
DispatchQueue.global().async { [unowned holder] in
continuation.resume(returning: holder.closure())
}
}
}
}
Expected behavior
with the withCheckedContinuation
function, the localBlock
closure should not escape the withoutActuallyEscaping
function call and should not trigger the "closure argument was escaped in withoutActuallyEscaping block" error
Environment
Apple Swift version 6.2-dev (LLVM f1be75e3e69fdf9, Swift f15d600)
Target: arm64-apple-macosx26.0
Build config: +assertions
Additional information
No response