func suspendResumeTask () async throws {
var contv: [CheckedContinuation <Void, Never>] = []
let i = 0
Task {
await withCheckedContinuation {
contv.append ($0)
print ("\(i) suspending")
}
print ("\(i) resumed")
}
try await Task.sleep(until: .now + .seconds(7))
for cont in contv {
cont.resume()
}
}
But, this one does not:
func suspendResumeTasks () async throws {
var contv: [CheckedContinuation <Void, Never>] = []
for i in 0..<1 {
Task {
await withCheckedContinuation {
contv.append ($0)
print ("\(i) suspending")
}
print ("\(i) resumed")
}
}
try await Task.sleep(until: .now + .seconds(7))
for cont in contv {
cont.resume()
}
What's being transferred here?
Error: Value of non-Sendable type ... accessed after being transferred; later accesses could race
Actual Error
Error: Value of non-Sendable type '@isolated(any) @async @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <()>' accessed after being transferred; later accesses could race
I don't think this should compile either. You have a mutable array of continuations, being passed to a task (requiring it to be in a disconnected region) and mutated, plus used after. Seems like another issue with Task diagnostic to me. The error cryptic here, it is contv that is being captured in an unsafe way.
While I don't know the underlying reason and it could be the same, the conditions in this case are at least slightly different. For me the diagnostics were correct when child task was not isolated to any global actor, but were missing when I specified one. Here there is no mention of any global actors, and warnings are still missing.