Swift accepts Ref and MutableRef for lifetime-bound access
SE-0519 accepts safe first-class references with the names Ref and MutableRef. Their constraints extend Swift's ownership model without making borrowed storage independently owned.
Swift's language steering group accepted SE-0519 with modifications on May 4, 2026. The accepted names are Ref and MutableRef. Earlier review material calls them Borrow and Inout, which explains the older names in the discussion's title. The decision accepts a design. It should not be read as an announcement that every installed Swift toolchain already supports it.
The naming discussion is useful because it concerns what programmers should understand about the values. The steering group treats them as references and connects them conceptually to single-element versions of Span and MutableSpan. It also acknowledges that the extended review did not reach a clear naming consensus. The accepted names follow the standard library's existing pattern for mutable variants.
I find this direction consistent with what I like about Swift. Standard collections give me value semantics with copy-on-write, and optionals make absence part of a type. I also keep the qualification in mind that references held inside a struct can still alias. A useful ownership model has to describe access to existing storage as carefully as it describes copying a value. These reference types address that concern at the level of the type system.
A reference carries an access restriction
The accepted proposal describes Ref as shared read access and MutableRef as exclusive mutable access. Both are nonescapable and carry lifetime dependencies on their targets. They allow access relationships to appear as values outside the immediate parameter list of a function. The target remains subject to the corresponding borrowing or exclusive-access restriction while the dependent reference is in use.
That is the essential distinction I would explain before showing an example. A reference to existing storage does not become an independent owner of that storage. Code that wants a value to persist independently needs a design that supplies ownership. Code that wants temporary access needs a design that proves the access cannot outlive its source. Those are different requirements, and an API should make the intended one visible.
The proposal makes the immutable reference copyable and the mutable reference noncopyable. This matches the access agreement. Shared readers can coexist, whereas copying an exclusive mutable capability would conflict with exclusivity. The details are especially useful to library authors who want to expose a temporary view into a larger value without requiring callers to manipulate unsafe pointers.
My own interest is in reviewing those agreements. I would ask what owns the target, what operations remain available during the reference's lifetime, and what prevents the reference from outliving that target. A concise type name cannot answer those questions on its own. The reference's constraints and the surrounding function signature need to provide the explanation.
Nonescapability is separate from copying
The foundation for this work is SE-0446 on nonescapable types. It introduces Escapable as a suppressible capability. Ordinary Swift types retain escapability by default. A declaration using ~Escapable opts into restrictions on moving values beyond their permitted context. The proposal deliberately keeps that concept separate from Copyable.
A value can be copyable while remaining nonescapable. Local copies must satisfy the same lifetime restriction as the original. That is useful for an iterator-like view where making a second local position is reasonable, but keeping the view after its storage disappears would be invalid. Conversely, preventing copies alone does not prove that a value cannot escape. A single surviving value can still refer to storage that has already ceased to exist.
This explains why noncopyable types could not solve the whole problem. The earlier proposal discusses iterators that need to be copied locally while retaining a relationship to their source. Copyability concerns how many values can exist. Escapability concerns where those values can be used or stored. Lifetime dependence supplies the further relationship between a view and the storage it describes.
The generic spelling also deserves care. In a generic requirement, ~Escapable suppresses the default requirement that an argument must be escapable. It permits both escapable and nonescapable arguments. Code using such an argument has to respect the possibility that it is nonescapable. Reading the tilde as a universal assertion that every supplied type must lack the capability would give the wrong interpretation.
I would teach that distinction before asking someone to design a generic wrapper. The wrapper needs to state which capabilities it requires from its contents and which it can provide conditionally. Otherwise the generic declaration may exclude the very reference types the wrapper was intended to support. This is a case where a small amount of syntax carries a substantial API design decision.
Restrictions propagate through storage
SE-0446 requires a type containing nonescapable stored values to be nonescapable itself. An ordinary escaping struct cannot hide such a value in one of its fields. Class properties also cannot provide a way around the restriction, since classes are inherently escaping in that design. Globals and static variables cannot hold these locally constrained values either.
Those rules explain why a safe view cannot be added to an arbitrary container without considering the container's own lifetime. The containing type participates in the same restriction. I would check a wrapper's storage before considering its convenience methods. If the wrapper is supposed to persist independently, its design needs owned data or another valid ownership arrangement.
Closures provide another boundary. SE-0446 prohibits escaping closures from capturing nonescapable values. A nonescaping closure can capture them subject to exclusivity rules. The proposal also points out that closures supplied to ordinary task creation APIs are escaping. An asynchronous operation therefore needs more careful analysis than simply observing that the code appears within a local block.
I find this a useful correction to casual reasoning about asynchronous work. Lexical nesting makes source code look local, but the relevant question is the lifetime that the operation permits. In a review, I would ask for the actual closure and parameter requirements. I would not infer safety from indentation or from the expectation that the operation will probably finish quickly.
Conditional escapability gives a wrapper another useful option. SE-0446 describes a generic container that starts as nonescapable and gains escapability when its element type has that capability. The container can preserve the restrictions of its contents without imposing the same restriction on every use. I would inspect that conditional conformance during an API review, especially if the wrapper is meant to accept both owned values and temporary views. Its convenience methods must continue to respect the weaker guarantees available for the general case.
Lifetime dependence permits useful results
Nonescapability alone would make construction awkward because an initializer must return the value it constructs. SE-0446 identifies lifetime dependencies as the mechanism needed to relate such a result to an input. A view can then leave the initializer while remaining constrained by the input's permitted lifetime. The compiler needs that relationship to distinguish useful construction from an invalid escape.
The earlier proposal treats the full lifetime-annotation design separately and describes initialization using experimental lifetime dependencies. That history is a reason to distinguish accepted reference types from a complete, universally available notation for every lifetime relationship. Library authors should check the supported toolchain and feature requirements of the exact interface they intend to publish.
For an evaluation, I would want both positive and negative tests. A positive test should show the intended temporary access. A negative compiler test should attempt to keep the view beyond its owner or create a conflicting access. The rejection is part of the API's purpose. A demonstration that only compiles valid code does not establish that an unsafe use has become impossible.
My Swift experience is still limited enough that I value explicit boundaries in low-level APIs. I would use these types where borrowing existing storage is a real requirement and where the lifetime constraints remain understandable to callers. For a value that must be stored independently or passed into unrelated work, I would start by deciding who owns it. That ownership decision should precede the choice of a reference wrapper.
The immediate consequence of the acceptance is a defined direction for safe first-class references, including their final names. When assessing a library that adopts the design, I would read its toolchain requirements alongside its access rules. The documentation should identify the owner of borrowed storage and describe which operations callers must postpone until the borrow ends. Those details determine whether the interface is usable in a particular application.