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 a type whose values can safely cross a concurrency boundary without introducing a data race. That boundary might be an actor, a new task, or a concurrent closure.
Structs and enums whose stored properties are all Sendable get the conformance implicitly, except public types, which must declare it. Classes must prove safety themselves, usually by being final with only immutable Sendable properties. Otherwise they can adopt @unchecked Sendable to opt out of compile-time checking.
In Swift 6 language mode, passing a non-Sendable value across a concurrency boundary is a compile-time error. The compiler enforces isolation instead of leaving data-race safety to runtime.
Parameter modifiers (borrowing, consuming, inout) and mutating describe how a value moves between caller and callee. They make ownership explicit and work with Swift's exclusive access rule, which forbids two overlapping accesses to the same variable when one of them writes.
Principles
Sendablevalues are safe to cross concurrency boundaries, and Swift 6 checks this at actor calls and task closures.- Non-public structs with
Sendablestored properties conform automatically, while classes must prove thread safety themselves. @unchecked Sendablesilences the compiler, so you take full responsibility for data-race safety.- Prefer immutable types across concurrency boundaries, and put shared mutable state in an actor.
func utf8Count(_ text: borrowing String) -> Int {
text.utf8.count // borrowed for this call only, so the caller still owns text
}
func logThenDrop(_ message: consuming String) {
print(message)
}
logThenDrop("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 a var binding so self can change



