Ownership, Noncopyable and Nonescapable Types
26.1 Parameter Ownership Modifiers (Swift 5.9)
func inspect(_ value: borrowing [Int]) { print(value.count) } // read-only borrow, no copy
func store(_ value: consuming [Int]) -> Storage { Storage(items: value) } // takes ownership (a move)
var list = [1, 2, 3]
let storage = store(consume list) // explicit `consume` ends list's lifetime
// print(list) // error: list was consumed
var copyList = copy list // explicit copy (in contexts where copies are restricted)26.2 Noncopyable Types (~Copyable)
Noncopyable generics (Swift 6.0): struct Box<T: ~Copyable>: ~Copyable, and Optional/Result support noncopyable payloads.
Use cases: unique resources (file handles, locks, tokens), linear types (a must-consume-once API), performance (avoiding ARC traffic).
struct FileDescriptor: ~Copyable { // can't be implicitly copied: unique ownership
private let fd: Int32
init(path: String) { fd = open(path, O_RDONLY) }
borrowing func read(count: Int) -> [UInt8] { [] } // borrows self
consuming func close() { // consumes self: no use afterwards
discard self // skip deinit after manual cleanup
_ = Darwin.close(fd)
}
deinit { _ = Darwin.close(fd) } // structs can have deinit when noncopyable
}
let file = FileDescriptor(path: "/etc/hosts")
let bytes = file.read(count: 10)
file.close()
// file.read(count: 1) // error: file was consumed26.3 Nonescapable Types and Span (Swift 6.2)
~Escapable types can't outlive the value they borrow from (lifetime-dependent).
Span<T> / RawSpan / MutableSpan: safe, efficient views over contiguous memory (a safer alternative to UnsafeBufferPointer). InlineArray<N, T> (6.2) is a fixed-size array stored inline ([5 of Int] shorthand in Swift 6.2).
let numbers = [1, 2, 3, 4]
let span = numbers.span // Span<Int> (Swift 6.2): bounds-checked, no copies
var total = 0
for i in span.indices { total += span[i] }
var buffer: InlineArray<4, Int> = [0, 0, 0, 0] // no heap allocation
buffer[0] = 42