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 consumed

26.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