Swift’s Ownership And Noncopyable Types
For nearly a decade, Swift’s relationship to memory looked settled. Classes were reference-counted automatically, structs and enums were copied freely, and the whole system ran quietly in the background without asking developers to think about ownership at all. Then, starting with Swift 5.9 in 2023, Apple began introducing a set of features, borrowing, consuming, and noncopyable types, that read like a direct answer to the question Rust had already spent years answering with its borrow checker. Swift got there slowly, on its own terms, and arguably ended up with something more forgiving in the process.
Where Swift Started
Swift launched in 2014 with automatic reference counting already baked in, inherited from Objective-C’s ARC model. The pitch was straightforward: classes get retained and released automatically by the compiler inserting the bookkeeping for you, so developers get the safety of garbage collection without the pause times that come with a tracing collector. Structs and enums, meanwhile, were designed to behave as value types, copied on assignment in principle, with copy-on-write optimizations under the hood so that a copy only actually happens in memory when one of the copies is mutated. This was a genuinely pleasant model to program against. It was also, by design, not something that gave programmers any direct control over when a value’s lifetime actually ended, and it could not express the idea of a resource, like a file handle or a hardware buffer, that should have exactly one owner at a time.
Rust, by contrast, built ownership into the language from its very first stable release in 2015. Every value in Rust has a single owner, moves transfer that ownership, and the compiler’s borrow checker statically verifies that no reference outlives the data it points to, all without a runtime cost. It was a genuinely novel proposition at the time, and it came with a real cost of its own: a notoriously steep learning curve, and a compiler that could feel like it was fighting the programmer over lifetime rules even when the underlying code was perfectly safe.
Swift’s Answer Arrives, Piece By Piece
Swift’s version of this idea arrived through a sequence of Swift Evolution proposals rather than as a single, all-at-once redesign. SE-0390, accepted in 2023, introduced noncopyable types: structs and enums that can be marked with a new suppression syntax, written as a tilde before the word Copyable, meaning the type opts out of Swift’s default assumption that every value can be freely duplicated. A noncopyable type behaves the way a class instance conceptually does, having a single owner at any given time, but without needing reference counting, since there is only ever one copy to track in the first place. Alongside it, SE-0377 introduced borrowing and consuming as explicit parameter modifiers, letting a function state directly whether it merely wants temporary, read-only access to a value or whether it intends to take full ownership and invalidate the caller’s copy. Both proposals landed together in Swift 5.9, released in September 2023.
That first release was intentionally limited. Noncopyable types could not be used inside generics, could not conform to protocols, and could not be boxed as existentials, restrictions the Swift Evolution proposal for SE-0390 acknowledged directly as an expressivity gap left for later work. That gap closed with SE-0427, noncopyable generics, which introduced a Copyable protocol that every struct, enum, generic parameter, and protocol conforms to by default, with the tilde syntax now understood as suppressing that default conformance rather than being a special case bolted onto the type system. SE-0427 shipped in Swift 6, released in September 2024, alongside SE-0429’s support for partially consuming just part of a noncopyable value and SE-0432’s support for borrowing during pattern matching rather than always consuming the value being switched over.
Convergence Without The Rigidity
The philosophical overlap with Rust is not subtle, and Apple’s own WWDC sessions on the topic draw the comparison openly, describing noncopyable types as a way to guarantee a value’s uniqueness the way Rust guarantees it, without giving up Swift’s existing defaults. The key difference is that Rust makes ownership tracking the default for every value in the language, while Swift makes it opt-in. An ordinary Swift struct remains copyable unless a developer explicitly suppresses that with the tilde syntax, which means the vast majority of existing Swift code, and the vast majority of new code that never touches a scarce resource, never has to think about ownership at all. Rust’s borrow checker applies uniformly whether a value is an integer or a network socket; Swift’s ownership model only switches on when a type specifically declares that copying it would be meaningless or dangerous, such as a file descriptor, a lock guard, or a unique hardware handle.
That opt-in design is also why Swift’s version arrived so gradually. Rust could build ownership into its type system from the first stable release because there was no prior version of the language with different defaults to stay compatible with. Swift had almost a decade of code written against a copy-friendly, reference-counted model already in production across the App Store, and introducing strict ownership rules as anything other than an additive, opt-in feature would have broken most of it. The result is that Apple’s convergence with Rust’s philosophy took nine years to begin and is still being filled in with proposals like SE-0446’s nonescapable types, but each piece has landed without forcing existing Swift code to change.
Comparing The Two Models
| Aspect | Rust | Swift |
|---|---|---|
| Default for a new type | Ownership tracked, no implicit copies | Freely copyable, unless explicitly suppressed |
| Ordinary reference types | Rc and Arc for shared ownership, manually chosen | Automatic reference counting for every class, by default |
| Learning curve for ordinary code | Steep, the borrow checker applies everywhere | Unchanged, ownership rules only apply where opted in |
What noncopyable types are actually for
- Modeling a resource that should have exactly one owner, such as a file handle, a socket, or a hardware buffer
- Giving structs and enums their own deinitializers, a capability previously reserved for classes
- Eliminating reference-counting overhead for types that never needed to be shared in the first place
- Letting a function’s signature declare, through borrowing or consuming, exactly what happens to a value’s lifetime when it’s passed in
What We Learned
Swift did not copy Rust’s borrow checker; it built its own, narrower version of the same underlying idea, and it did so as an addition rather than a replacement. Automatic reference counting still handles the overwhelming majority of Swift code exactly as it always has, and the new ownership machinery only activates for the specific types a developer chooses to mark as noncopyable. That is a real trade-off against Rust’s approach, where uniform ownership tracking gives the compiler stronger guarantees across the entire codebase, not just the parts a developer singled out.
But for a language with a decade of existing production code behind it, opt-in was the only realistic path, and the fact that Apple got there at all, across five years of Swift Evolution proposals rather than a single breaking rewrite, says something about how far the industry’s appetite for ownership-based safety has spread beyond Rust’s original audience.




