Question 9
Sendable, ownership, and mutability
What does Sendable communicate to the compiler? How does it relate to actor isolation and mutability in Swift 6 concurrency?
Answer outline
Sendable marks types whose values can safely cross concurrency boundaries — into actor-isolated contexts, tasks, or concurrent closures, without introducing data races.
Value types whose stored properties are all Sendable conform automatically. Classes must prove safety manually, or use @unchecked Sendable to opt out of compile-time verification.
In Swift 6, passing a non-Sendable value across a concurrency boundary is a compile-time error. The compiler enforces isolation rather than leaving data-race safety to runtime.
Ownership modifiers (borrowing, consuming, inout) and mutating describe how values move between caller and callee — they reinforce value-type safety and exclusive access guarantees.
Principles
Sendablevalues are safe to cross concurrency boundaries — Swift 6 enforces this at actor call sites and task closures.- Structs with
Sendablestored properties conform automatically; classes must manually prove thread safety. @unchecked Sendablesilences the compiler — you take full responsibility for data-race safety.- Prefer immutable types across concurrency boundaries; use actors for shared mutable state.
func utf8Count(borrowing text: String) -> Int {
text.utf8.count // read-only for this call; caller still owns text afterward
}
func logThenDrop(consuming message: String) {
print(message)
}
logThenDrop(consuming: "done")
func double(_ value: inout Int) {
value *= 2
}
var x = 3
double(&x)
// x is now 6
struct Counter {
var n = 0
mutating func tick() { n += 1 }
}
var c = Counter()
c.tick() // needs var binding so self can change