'Is it safe to make a struct containing a closure Sendable?

I want to have a Sendable struct, which contains a closure. This closure takes in a reference type, but returns Void, therefore the Greeter doesn't directly stores the Person reference. However, closures themselves are still references anyway.

Current code:

class Person {
    let name: String

    init(name: String) {
        self.name = name
    }
}

struct Greeter: Sendable { // <- Trying to make this Sendable
    let greet: (Person) -> Void

    init(greeting: String) {
        greet = { person in
            print("\(greeting), \(person.name)!")
        }
    }
}
let person = Person(name: "George")
let greeter = Greeter(greeting: "Hello")
greeter.greet(person)

// Hello, George!

In my actual problem (this is simplified) I don't actually know Person's implementation and so can't mark it Sendable. It's actually a MTLRenderCommandEncoder, but for simplicity we just have Person.

On the greet definition, I get the following warning:

Stored property 'greet' of 'Sendable'-conforming struct 'Greeter' has non-sendable type '(Person) -> Void'

I can make the warnings go away, but I don't think it's the safe & correct solution:

struct Greeter: Sendable {
    let greet: @Sendable (Person) -> Void

    init(greeting: String) {
        greet = { @Sendable person in
            print("\(greeting), \(person.name)!")
        }
    }
}

How can I be sure this code is safe across threads?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source