Why is this closure @Sendable?


I was exploring the proposal for Sendable and @Sendable closures this afternoon and saw this example of a non-sendable closure:

// Error: cannot capture NSMutableString in a @Sendable closure!
list = await contactList.filteredElements {
  $0.firstName == nsMutableName

Since it lacks some context, I figured the follow should follow the example close enough and I expected to see a warning and / or an error here (Swift 5.6 so I think most things would still be warnings).

actor Sample {
    func execute(_ fn: @Sendable () -> Bool) {
        _ = fn()

class Test {
    let sample = Sample()
    var str: NSMutableString = ""
    func goForIt() async {
        await sample.execute({
            str = "hello"
            return str == "hello"

Hopefully somebody can explain a bit why it's okay for me to be mutating sate in this (supposedly) Sendable closure while it seems like that shouldn't be allowed.

You will get a warning if you enable strict concurrency checking by using the -warn-concurrency flag.

str = "hello" // warning: Capture of 'self' with non-sendable type 'Test' in a `@Sendable` closure

In a Swift Package you can enable strict concurrency checking by adding the following flags in swiftSettings to your target:

swiftSettings: [.unsafeFlags(["-Xfrontend", "-warn-concurrency"])]
1 Like

Ahh okay! I had added that to check whether that would pop up the warning I expected but looks like Xcode didn't properly pick it up until after I ran a clean build... Good to see I didn't completely misunderstand the proposal then.

Thanks, @dnadoba!

1 Like