Data Races & Sendable

I have a few questions about Sendable and it's limits.
As I understood Sendable objects can be shared between concurrency domains and therefore, have to be thread safe to avoid data races.
Additional to that the compiler should be able to automatically detect potential data races and warn you about those.

I wanted to know how much I can rely on those compiler checks.

In my example ViewModel is on purpose not sendable and causing data races (concurrent access to load will just crash).

class ViewModel {
    var data = [String]()

    func load() async {        
        for i in 0...1_000_000 {
            data.append("\(i)")
        }
    }
}

If I create a class that just calls that function I receive a warning that ViewModel is not sendable.

class SendableTest2 {
    let viewModel = ViewModel()
    
    func start() {
        
        Task {
            await viewModel.load()
        }
    }
}

If I do the same with an actor everything is fine for the compiler - but will also crash.

actor SendableTest1 {
    let viewModel = ViewModel()
    
    func start() async {
        var task: Task<Void, Never>?
        for _ in 0...1000 {
            task = Task {
                await viewModel.load()
            }
        }
        await task?.value
    }
}

So I understand why I don't receive a warning at the actor (because the property is isolated through the actor itself).
But still I would expect some kind of warning that data should not be accessed in an async function.
I am not even sure if Sendable is responsible for these kind of errors at all.

So my questions are:

  1. Is Sendable even solving these kind of data races?
  2. Will the compiler warn me at some point in the future (e.g. with Swift 6.0)?
  3. Is that something the developer has to take care of and the compiler & structured concurrency will never check for me?
  4. Is accessing data from multiple Tasks not the same thing as accessing it from multiple concurrency domains?

Tested on a device with iOS 16 - Xcode beta 14, Swift 5.7 and strict concurrency checking set to complete

2 Likes