<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hello, swift-evolution.</div><div class=""><br class=""></div><div class="">Memory ownership is a topic that keeps poking its head up here. Core team</div><div class="">members have mentioned several times that it's something we're interested in</div><div class="">working on. Questions sometimes get referred back to it, saying stuff like</div><div class="">"we're working on tools to let you control ARC a little better". It's even on the</div><div class="">short list of high-priority features for Swift 4:</div><div class=""><br class=""></div><div class=""> <a href="https://github.com/apple/swift-evolution" class="">https://github.com/apple/swift-evolution</a></div><div class=""><br class=""></div><div class=""> Memory ownership model: an (opt-in) Cyclone/Rust-inspired memory</div><div class=""> ownership model is highly desired by systems programmers and for other</div><div class=""> high-performance applications that want predictable and deterministic</div><div class=""> performance. This feature will fundamentally shape the ABI, from low-level</div><div class=""> language concerns such as "inout" and low-level "addressors" to its impact</div><div class=""> on the standard library. While a full memory ownership model is likely too</div><div class=""> large for Swift 4 stage 1, we need a comprehensive design to understand</div><div class=""> how it will change the ABI.</div><div class=""><br class=""></div><div class="">But that's all pretty vague. What is ownership? What does it mean for</div><div class="">programmers? Is somebody ever going to actually write that comprehensive</div><div class="">design that was supposed to come out during Stage 1?</div><div class=""><br class=""></div><div class="">Well, here you go.</div><div class=""><br class=""></div><div class="">I want to emphasize that this document is two things. It is a *manifesto*,</div><div class="">because it describes the whole problem and presents a holistic solution to it.</div><div class="">And it is a *meta-proposal*, because that holistic solution imagines and a number</div><div class="">of changes, each of which is worthy of a proposal; it is, essentially, a proposal</div><div class="">that we write a bunch of smaller proposals for each of these changes. But it's</div><div class="">not actually a concrete proposal for those smaller changes: it's often lacking in</div><div class="">that level of detail, and it leaves a number of questions open. This document, itself,</div><div class="">will not undergo the formal evolution process. And it may be that some of these</div><div class="">changes aren't really necessary, or that they need major reconsideration before</div><div class="">they're appropriate for proposal. But our hope — my hope — is that this</div><div class="">document is sufficient for you to understand the holistic approach we're suggesting,</div><div class="">or at least puts you in a position where you're comfortable asking questions</div><div class="">and trying to figure it out.</div><div class=""><br class=""></div><div class="">So, like I said, this isn't a formal proposal. What, then, are we hoping to achieve?</div><div class="">Well, we want people to talk about it. We'd like to achieve a consensus about</div><div class="">whether this basic approach makes sense for the language and achieves its goals.</div><div class="">And, assuming that the consensus is "yes" and that we should go forward with it,</div><div class="">we'd like this document — and this thread — to serve as an introduction to the</div><div class="">topic that we can refer back to when we're proposing and discussing all of those</div><div class="">changes in the weeks to come.</div><div class=""><br class=""></div><div class="">With that said, let's get started.</div><div class=""><br class=""></div><div class="">John.</div><div class=""><br class=""></div><div class="">------------------------------------------------------------------</div><div class=""><br class=""></div><div class=""># Ownership</div><div class=""><br class=""></div><div class="">## Introduction</div><div class=""><br class=""></div><div class="">Adding "ownership" to Swift is a major feature with many benefits</div><div class="">for programmers. This document is both a "manifesto" and a</div><div class="">"meta-proposal" for ownership: it lays out the basic goals of</div><div class="">the work, describes a general approach for achieving those goals,</div><div class="">and proposes a number of specific changes and features, each of</div><div class="">which will need to be separately discussed in a smaller and more</div><div class="">targeted proposal. This document is intended to provide a framework</div><div class="">for understanding the contributions of each of those changes.</div><div class=""><br class=""></div><div class="">### Problem statement</div><div class=""><br class=""></div><div class="">The widespread use of copy-on-write value types in Swift has generally</div><div class="">been a success. It does, however, come with some drawbacks:</div><div class=""><br class=""></div><div class="">* Reference counting and uniqueness testing do impose some overhead.</div><div class=""><br class=""></div><div class="">* Reference counting provides deterministic performance in most cases,</div><div class=""> but that performance can still be complex to analyze and predict.</div><div class=""><br class=""></div><div class="">* The ability to copy a value at any time and thus "escape" it forces</div><div class=""> the underlying buffers to generally be heap-allocated. Stack allocation</div><div class=""> is far more efficient but does require some ability to prevent, or at</div><div class=""> least recognize, attempts to escape the value.</div><div class=""><br class=""></div><div class="">Certain kinds of low-level programming require stricter performance</div><div class="">guarantees. Often these guarantees are less about absolute performance</div><div class="">than *predictable* performance. For example, keeping up with an audio</div><div class="">stream is not a taxing job for a modern processor, even with significant</div><div class="">per-sample overheads, but any sort of unexpected hiccup is immediately</div><div class="">noticeable by users.</div><div class=""><br class=""></div><div class="">Another common programming task is to optimize existing code when something</div><div class="">about it falls short of a performance target. Often this means finding</div><div class="">"hot spots" in execution time or memory use and trying to fix them in some</div><div class="">way. When those hot spots are due to implicit copies, Swift's current</div><div class="">tools for fixing the problem are relatively poor; for example, a programmer</div><div class="">can fall back on using unsafe pointers, but this loses a lot of the</div><div class="">safety benefits and expressivity advantages of the library collection types.</div><div class=""><br class=""></div><div class="">We believe that these problems can be addressed with an opt-in set of</div><div class="">features that we collectively call *ownership*.</div><div class=""><br class=""></div><div class="">### What is ownership?</div><div class=""><br class=""></div><div class="">*Ownership* is the responsibility of some piece of code to</div><div class="">eventually cause a value to be destroyed. An *ownership system*</div><div class="">is a set of rules or conventions for managing and transferring</div><div class="">ownership.</div><div class=""><br class=""></div><div class="">Any language with a concept of destruction has a concept of</div><div class="">ownership. In some languages, like C and non-ARC Objective-C,</div><div class="">ownership is managed explicitly by programmers. In other</div><div class="">languages, like C++ (in part), ownership is managed by the</div><div class="">language. Even languages with implicit memory management still</div><div class="">have libraries with concepts of ownership, because there are</div><div class="">other program resources besides memory, and it is important</div><div class="">to understand what code has the responsibility to release</div><div class="">those resources.</div><div class=""><br class=""></div><div class="">Swift already has an ownership system, but it's "under the covers":</div><div class="">it's an implementation detail that programmers have little</div><div class="">ability to influence. What we are proposing here is easy</div><div class="">to summarize:</div><div class=""><br class=""></div><div class="">- We should add a core rule to the ownership system, called</div><div class=""> the Law of Exclusivity, which requires the implementation</div><div class=""> to prevent variables from being simultaneously accessed</div><div class=""> in conflicting ways. (For example, being passed `inout`</div><div class=""> to two different functions.) This will not be an opt-in</div><div class=""> change, but we believe that most programs will not be</div><div class=""> adversely affected.</div><div class=""><br class=""></div><div class="">- We should add features to give programmers more control over</div><div class=""> the ownership system, chiefly by allowing the propagation</div><div class=""> of "shared" values. This will be an opt-in change; it</div><div class=""> will largely consist of annotations and language features</div><div class=""> which programmers can simply not use.</div><div class=""><br class=""></div><div class="">- We should add features to allow programmers to express</div><div class=""> types with unique ownership, which is to say, types that</div><div class=""> cannot be implicitly copied. This will be an opt-in</div><div class=""> feature intended for experienced programmers who desire</div><div class=""> this level of control; we do not intend for ordinary</div><div class=""> Swift programming to require working with such types.</div><div class=""><br class=""></div><div class="">These three tentpoles together have the effect of raising</div><div class="">the ownership system from an implementation detail to a more</div><div class="">visible aspect of the language. They are also somewhat</div><div class="">inseparable, for reasons we'll explain, although of course they</div><div class="">can be prioritized differently. For these reasons, we will</div><div class="">talk about them as a cohensive feature called "ownership".</div><div class=""><br class=""></div><div class="">### A bit more detail</div><div class=""><br class=""></div><div class="">The basic problem with Swift's current ownership system</div><div class="">is copies, and all three tentpoles of ownership are about</div><div class="">avoiding copies.</div><div class=""><br class=""></div><div class="">A value may be used in many different places in a program.</div><div class="">The implementation has to ensure that some copy of the value</div><div class="">survives and is usable at each of these places. As long as</div><div class="">a type is copyable, it's always possible to satisfy that by</div><div class="">making more copies of the value. However, most uses don't</div><div class="">actually require ownership of their own copy. Some do: a</div><div class="">variable that didn't own its current value would only be</div><div class="">able to store values that were known to be owned by something</div><div class="">else, which isn't very useful in general. But a simple thing</div><div class="">like reading a value out of a class instance only requires that</div><div class="">the instance still be valid, not that the code doing the</div><div class="">read actually own a reference to it itself. Sometimes the</div><div class="">difference is obvious, but often it's impossible to know.</div><div class="">For example, the compiler generally doesn't know how an</div><div class="">arbitrary function will use its arguments; it just falls</div><div class="">back on a default rule for whether to pass ownership of</div><div class="">the value. When that default rule is wrong, the program</div><div class="">will end up making extra copies at runtime. So one simple</div><div class="">thing we can do is allow programs to be more explicit at</div><div class="">certain points about whether they need ownership or not.</div><div class=""><br class=""></div><div class="">That closely dovetails with the desire to support non-copyable</div><div class="">types. Most resources require a unique point of destruction:</div><div class="">a memory allocation can only be freed once, a file can only</div><div class="">be closed once, a lock can only be released once, and so on.</div><div class="">An owning reference to such a resource is therefore naturally</div><div class="">unique and thus non-copyable. Of course, we can artificially</div><div class="">allow ownership to be shared by, say, adding a reference count</div><div class="">and only destroying the resource when the count reaches zero.</div><div class="">But this can substantially increase the overhead of working</div><div class="">with the resource; and worse, it introduces problems with</div><div class="">concurrency and re-entrancy. If ownership is unique, and the</div><div class="">language can enforce that certain operations on a resource</div><div class="">can only be performed by the code that owns the resource,</div><div class="">then by construction only one piece of code can perform those</div><div class="">operations at a time. As soon as ownership is shareable,</div><div class="">that property disappears. So it is interesting for the</div><div class="">language to directly support non-copyable types because they</div><div class="">allow the expression of optimally-efficient abstractions</div><div class="">over resources. However, working with such types requires</div><div class="">all of the abstraction points like function arguments to</div><div class="">be correctly annotated about whether they transfer ownership,</div><div class="">because the compiler can no longer just make things work</div><div class="">behind the scenes by adding copies.</div><div class=""><br class=""></div><div class="">Solving either of these problems well will require us to</div><div class="">also solve the problem of non-exclusive access to variables.</div><div class="">Swift today allows nested accesses to the same variable;</div><div class="">for example, a single variable can be passed as two different</div><div class="">`inout` arguments, or a method can be passed a callback that</div><div class="">somehow accesses the same variable that the method was called on.</div><div class="">Doing this is mostly discouraged, but it's not forbidden,</div><div class="">and both the compiler and the standard library have to bend</div><div class="">over backwards to ensure that the program won't misbehave</div><div class="">too badly if it happens. For example, `Array` has to retain</div><div class="">its buffer during an in-place element modification; otherwise,</div><div class="">if that modification somehow reassigned the array variable,</div><div class="">the buffer would be freed while the element was still being</div><div class="">changed. Similarly, the compiler generally finds it difficult</div><div class="">to prove that values in memory are the same at different points</div><div class="">in a function, because it has to assume that any opaque</div><div class="">function call might rewrite all memory; as a result, it</div><div class="">often has to insert copies or preserve redundant loads</div><div class="">out of paranoia. Worse, non-exclusive access greatly</div><div class="">limits the usefulness of explicit annotations. For example,</div><div class="">a "shared" argument is only useful if it's really guaranteed</div><div class="">to stay valid for the entire call, but the only way to</div><div class="">reliably satisfy that for the current value of a variable</div><div class="">that can be re-entrantly modified is to make a copy and pass</div><div class="">that instead. It also makes certain important patterns</div><div class="">impossible, like stealing the current value of a variable</div><div class="">in order to build something new; this is unsound if the</div><div class="">variable can be accessed by other code in the middle.</div><div class="">The only solution to this is to establish a rule that prevents</div><div class="">multiple contexts from accessing the same variable at the</div><div class="">same time. This is what we propose to do with the Law</div><div class="">of Exclusivity.</div><div class=""><br class=""></div><div class="">All three of these goals are closely linked and mutually</div><div class="">reinforcing. The Law of Exclusivity allows explicit annotations</div><div class="">to actually optimize code by default and enables mandatory</div><div class="">idioms for non-copyable types. Explicit annotations create</div><div class="">more optimization opportunities under the Law and enable</div><div class="">non-copyable types to function. Non-copyable types validate</div><div class="">that annotations are optimal even for copyable types and</div><div class="">create more situations where the Law can be satisfied statically.</div><div class=""><br class=""></div><div class="">### Criteria for success</div><div class=""><br class=""></div><div class="">As discussed above, it is the core team's expectation that</div><div class="">ownership can be delivered as an opt-in enhancement to Swift.</div><div class="">Programmers should be able to largely ignore ownership and not</div><div class="">suffer for it. If this expectation proves to not be satisfiable,</div><div class="">we will reject ownership rather than imposing substantial</div><div class="">burdens on regular programs.</div><div class=""><br class=""></div><div class="">The Law of Exclusivity will impose some new static and dynamic</div><div class="">restrictions. It is our belief that these restrictions will only</div><div class="">affect a small amount of code, and only code that does things</div><div class="">that we already document as producing unspecified results.</div><div class="">These restrictions, when enforced dynamically, will also hurt</div><div class="">performance. It is our hope that this will be "paid for" by</div><div class="">the improved optimization potential. We will also provide tools</div><div class="">for programmers to eliminate these safety checks where necessary.</div><div class="">We will discuss these restrictions in greater detail later in this</div><div class="">document.</div><div class=""><br class=""></div><div class="">## Core definitions</div><div class=""><br class=""></div><div class="">### Values</div><div class=""><br class=""></div><div class="">Any discussion of ownership systems is bound to be at a lower</div><div class="">level of abstraction. We will be talking a lot about</div><div class="">implementation topics. In this context, when we say "value",</div><div class="">we mean a specific instance of a semantic, user-language value.</div><div class=""><br class=""></div><div class="">For example, consider the following Swift code:</div><div class=""><br class=""></div><div class="">```</div><div class=""> var x = [1,2,3]</div><div class=""> var y = x</div><div class="">```</div><div class=""><br class=""></div><div class="">People would often say that `x` and `y` have the same value</div><div class="">at this point. Let's call this a *semantic value*. But at</div><div class="">the level of the implementation, because the variables `x` and `y`</div><div class="">can be independently modified, the value in `y` must be a</div><div class="">copy of the value in `x`. Let's call this a *value instance*.</div><div class="">A value instance can be moved around in memory and remain the</div><div class="">same value instance, but a copy always yields a new value instance.</div><div class="">For the remainder of this document, when we use "value" without any</div><div class="">qualification, we mean it in this low-level sense of value instance.</div><div class=""><br class=""></div><div class="">What it means to copy or destroy a value instance depends on the type:</div><div class=""><br class=""></div><div class="">* Some types do not require extra work besides copying their</div><div class=""> byte-representation; we call these *trivial*. For example,</div><div class=""> `Int` and `Float` are trivial types, as are ordinary `struct`s</div><div class=""> and `enum`s containing only such values. Most of what we have</div><div class=""> to say about ownership in this document doesn't apply to the</div><div class=""> values of such types. However, the Law of Exclusivity will still</div><div class=""> apply to them.</div><div class=""><br class=""></div><div class="">* For reference types, the value instance is a reference to an object.</div><div class=""> Copying the value instance means making a new reference, which</div><div class=""> increases the reference count. Destroying the value instance means</div><div class=""> destroying a reference, which decreases the reference count. Decreasing</div><div class=""> the reference count can, of course, drop it to zero and thus destroy</div><div class=""> the object, but it's important to remember that all this talk about</div><div class=""> copying and destroying values means manipulating reference counts,</div><div class=""> not copying the object or (necessarily) destroying it.</div><div class=""><br class=""></div><div class="">* For copy-on-write types, the value instance includes a reference to</div><div class=""> a buffer, which then works basically like a reference type. Again,</div><div class=""> it is important to remember that copying the value doesn't mean</div><div class=""> copying the contents of the buffer into a new buffer.</div><div class=""><br class=""></div><div class="">There are similar rules for every kind of type.</div><div class=""><br class=""></div><div class="">### Memory</div><div class=""><br class=""></div><div class="">In general, a value can be owned in one of two ways: it can be</div><div class="">"in flight", a temporary value owned by a specific execution context</div><div class="">which computed the value as an operand, or it can be "at rest",</div><div class="">stored in some sort of memory.</div><div class=""><br class=""></div><div class="">We don't need to focus much on temporary values because their</div><div class="">ownership rules are straightforward. Temporary values are created</div><div class="">as the result of some expression; that expression is used in some</div><div class="">specific place; the value is needed in that place and not</div><div class="">thereafter; so the implementation should clearly take all possible</div><div class="">steps to forward the value directly to that place instead of</div><div class="">forcing it to be copied. Users already expect all of this to</div><div class="">happen, and there's nothing really to improve here.</div><div class=""><br class=""></div><div class="">Therefore, most of our discussion of ownership will center around</div><div class="">values stored in memory. There are five closely related concepts</div><div class="">in Swift's treatment of memory.</div><div class=""><br class=""></div><div class="">A *storage declaration* is the language-syntax concept of a declaration</div><div class="">that can be treated in the language like memory. Currently, these are</div><div class="">always introduced with `let`, `var`, and `subscript`. A storage</div><div class="">declaration has a type. It also has an implementation which defines</div><div class="">what it means to read or write the storage. The default implementation</div><div class="">of a `var` or `let` just creates a new variable to store the value,</div><div class="">but storage declarations can also be computed, and so there needn't</div><div class="">be any variables at all behind one.</div><div class=""><br class=""></div><div class="">A *storage reference expression* is the syntax concept of an expression</div><div class="">that refers to storage. This is similar to the concept from other</div><div class="">languages of an "l-value", except that it isn't necessarily usable on</div><div class="">the left side of an assignment because the storage doesn't have to be</div><div class="">mutable.</div><div class=""><br class=""></div><div class="">A *storage reference* is the language-semantics concept of a fully</div><div class="">filled-in reference to a specific storage declaration. In other</div><div class="">words, it is the result of evaluating a storage reference expression</div><div class="">in the abstract, without actually accessing the storage. If the</div><div class="">storage is a member, this includes a value or storage reference</div><div class="">for the base. If the storage is a subscript, this includes a value</div><div class="">for the index. For example, a storage reference expression like</div><div class="">`widgets[i].weight` might abstractly evaluate to this storage reference:</div><div class=""><br class=""></div><div class="">* the storage for the property `var weight: Double` of</div><div class="">* the storage for the subscript `subscript(index: Int)` at index value `19: Int` of</div><div class="">* the storage for the local variable `var widgets: [Widget]`</div><div class=""><br class=""></div><div class="">A *variable* is the semantics concept of a unique place in</div><div class="">memory that stores a value. It's not necessarily mutable, at least</div><div class="">as we're using it in this document. Variables are usually created for</div><div class="">storage declarations, but they can also be created dynamically in</div><div class="">raw memory, e.g. using UnsafeRawPointer. A variable always has a</div><div class="">specific type. It also has a *lifetime*, i.e. a point in the language</div><div class="">semantics where it comes into existence and a point (or several)</div><div class="">where it is destroyed.</div><div class=""><br class=""></div><div class="">A *memory location* is a contiguous range of addressable memory. In</div><div class="">Swift, this is mostly an implementation concept. Swift does not</div><div class="">guarantee that any particular variable will have a consistent memory</div><div class="">location throughout its lifetime, or in fact be stored in a memory</div><div class="">location at all. But a variable can sometimes be temporarily forced</div><div class="">to exist at a specific, consistent location: e.g. it can be passed</div><div class="">`inout` to `withUnsafeMutablePointer`.</div><div class=""><br class=""></div><div class="">### Accesses</div><div class=""><br class=""></div><div class="">A particular evaluation of a storage reference expression is</div><div class="">called an access. Accesses come in three kinds: *reads*,</div><div class="">*assignments*, and *modifications*. Assignments and modifications</div><div class="">are both *writes*, with the difference being that an assignment</div><div class="">completely replaces the old value without reading it, while a</div><div class="">modification does rely on the old value.</div><div class=""><br class=""></div><div class="">All storage reference expressions are classified into one of these</div><div class="">three kinds of access based on the context in which the expression</div><div class="">appears. It is important to note that this decision is superficial:</div><div class="">it relies only on the semantic rules of the immediate context, not</div><div class="">on a deeper analysis of the program or its dynamic behavior.</div><div class="">For example, a storage reference passed as an `inout` argument</div><div class="">is always evaluated as a modification in the caller, regardless</div><div class="">of whether the callee actually uses the current value, performs</div><div class="">any writes to it, or even refers to it at all.</div><div class=""><br class=""></div><div class="">The evaluation of a storage reference expression is divided into</div><div class="">two phases: it is first formally evaluated to a storage reference,</div><div class="">and then a formal access to that storage reference occurs for some</div><div class="">duration. The two phases are often evaluated in immediate</div><div class="">succession, but they can be separated in complex cases, such as</div><div class="">when an `inout` argument is not the last argument to a call.</div><div class="">The purpose of this phase division is to minimize the duration of</div><div class="">the formal access while still preserving, to the greatest extent</div><div class="">possible, Swift's left-to-right evaluation rules.</div><div class=""><br class=""></div><div class="">## The Law of Exclusivity</div><div class=""><br class=""></div><div class="">With all of that established, we can succinctly state the first</div><div class="">part of this proposal, the Law of Exclusivity:</div><div class=""><br class=""></div><div class="">> If a storage reference expression evaluates to a storage</div><div class="">> reference that is implemented by a variable, then the formal</div><div class="">> access duration of that access may not overlap the formal</div><div class="">> access duration of any other access to the same variable</div><div class="">> unless both accesses are reads.</div><div class=""><br class=""></div><div class="">This is intentionally vague: it merely says that accesses</div><div class="">"may not" overlap, without specifying how that will be</div><div class="">enforced. This is because we will use different enforcement</div><div class="">mechanisms for different kinds of storage. We will discuss</div><div class="">those mechanisms in the next major section. First, however,</div><div class="">we need to talk in general about some of the implications of</div><div class="">this rule and our approach to satisfying it.</div><div class=""><br class=""></div><div class="">### Duration of exclusivity</div><div class=""><br class=""></div><div class="">The Law says that accesses must be exclusive for their entire</div><div class="">formal access duration. This duration is determined by the</div><div class="">immediate context which causes the access; that is, it's a</div><div class="">*static* property of the program, whereas the safety problems</div><div class="">we laid out in the introduction are *dynamic*. It is a general</div><div class="">truth that static approaches to dynamic problems can only be</div><div class="">conservatively correct: there will be dynamically-reasonable</div><div class="">programs that are nonetheless rejected. It is fair to ask how</div><div class="">that general principle applies here.</div><div class=""><br class=""></div><div class="">For example, when storage is passed as an `inout` argument, the</div><div class="">access lasts for the duration of the call. This demands</div><div class="">caller-side enforcement that no other accesses can occur to</div><div class="">that storage during the call. Is it possible that this is too</div><div class="">coarse-grained? After all, there may be many points within the</div><div class="">called function where it isn't obviously using its `inout`</div><div class="">argument. Perhaps we should track accesses to `inout` arguments</div><div class="">at a finer-grained level, within the callee, instead of attempting</div><div class="">to enforce the Law of Exclusivity in the caller. The problem</div><div class="">is that that idea is simply too dynamic to be efficiently</div><div class="">implemented.</div><div class=""><br class=""></div><div class="">A caller-side rule for `inout` has one key advantage: the</div><div class="">caller has an enormous amount of information about what</div><div class="">storage is being passed. This means that a caller-side rule</div><div class="">can often be enforced purely statically, without adding dynamic</div><div class="">checks or making paranoid assumptions. For example, suppose</div><div class="">that a function calls a `mutating` method on a local variable.</div><div class="">(Recall that `mutating` methods are passed `self` as an `inout`</div><div class="">argument.) Unless the variable has been captured in an</div><div class="">escaping closure, the function can easily examine every</div><div class="">access to the variable to see that none of them overlap</div><div class="">the call, thus proving that the rule is satisfied. Moreover,</div><div class="">that guarantee is then passed down to the callee, which can</div><div class="">use that information to prove the safety of its own accesses.</div><div class=""><br class=""></div><div class="">In contrast, a callee-side rule for `inout` cannot take</div><div class="">advantage of that kind of information: the information is</div><div class="">simply discarded at the point of the call. This leads to the</div><div class="">widespread optimization problems that we see today, as</div><div class="">discussed in the introduction. For example, suppose that</div><div class="">the callee loads a value from its argument, then calls</div><div class="">a function which the optimizer cannot reason about:</div><div class=""><br class=""></div><div class="">```</div><div class=""> extension Array {</div><div class=""> mutating func organize(_ predicate: (Element) -> Bool) {</div><div class=""> let first = self[0]</div><div class=""> if !predicate(first) { return }</div><div class=""> ...</div><div class=""> // something here uses first</div><div class=""> }</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">Under a callee-side rule, the optimizer must copy `self[0]`</div><div class="">into `first` because it must assume (paranoidly) that</div><div class="">`predicate` might somehow turn around and modify the</div><div class="">variable that `self` was bound to. Under a caller-side</div><div class="">rule, the optimizer can use the copy of value held in the</div><div class="">array element for as long as it can continue to prove that</div><div class="">the array hasn't been modified.</div><div class=""><br class=""></div><div class="">Moreover, as the example above suggests, what sort of code</div><div class="">would we actually be enabling by embracing a callee-side rule?</div><div class="">A higher-order operation like this should not have to worry</div><div class="">about the caller passing in a predicate that re-entrantly</div><div class="">modifies the array. Simple implementation choices, like</div><div class="">making the local variable `first` instead of re-accessing</div><div class="">`self[0]` in the example above, would become semantically</div><div class="">important; maintaining any sort of invariant would be almost</div><div class="">inconceivable. It is no surprise that Swift's libraries</div><div class="">generally forbid this kind of re-entrant access. But,</div><div class="">since the library can't completely prevent programmers</div><div class="">from doing it, the implementation must nonetheless do extra</div><div class="">work at runtime to prevent such code from running into</div><div class="">undefined behavior and corrupting the process. Because it</div><div class="">exists solely to work around the possibility of code that</div><div class="">should never occur in a well-written program, we see this</div><div class="">as no real loss.</div><div class=""><br class=""></div><div class="">Therefore, this proposal generally proposes access-duration</div><div class="">rules like caller-side `inout` enforcement, which allow</div><div class="">substantial optimization opportunities at little semantic</div><div class="">cost.</div><div class=""><br class=""></div><div class="">### Components of value and reference types</div><div class=""><br class=""></div><div class="">We've been talking about *variables* a lot. A reader might</div><div class="">reasonably wonder what all this means for *properties*.</div><div class=""><br class=""></div><div class="">Under the definition we laid out above, a property is a</div><div class="">storage declaration, and a stored property creates a</div><div class="">corresponding variable in its container. Accesses to that</div><div class="">variable obviously need to obey the Law of Exclusivity, but are</div><div class="">there any additional restrictions in play due to the fact</div><div class="">that the properties are organized together into a container?</div><div class="">In particular, should the Law of Exclusivity prevent accesses</div><div class="">to different properties of the same variable or value from</div><div class="">overlapping?</div><div class=""><br class=""></div><div class="">Properties can be classified into three groups:</div><div class="">- instance properties of value types,</div><div class="">- instance properties of reference types, and</div><div class="">- `static` and `class` properties on any kind of type.</div><div class=""><br class=""></div><div class="">We propose to always treat reference-type and `static` properties</div><div class="">as independent from one another other, but to treat value-type</div><div class="">properties as generally non-independent outside of a specific</div><div class="">(but important) special case. That's a potentially significant</div><div class="">restriction, and it's reasonable to wonder both why it's necessary</div><div class="">and why we need to draw this distinction between different</div><div class="">kinds of property. There are three reasons.</div><div class=""><br class=""></div><div class="">#### Independence and containers</div><div class=""><br class=""></div><div class="">The first relates to the container.</div><div class=""><br class=""></div><div class="">For value types, it is possible to access both an individual</div><div class="">property and the entire aggregate value. It is clear that an</div><div class="">access to a property can conflict with an access to the aggregate,</div><div class="">because an access to the aggregate is essentially an access to</div><div class="">all of the properties at once. For example, consider a variable</div><div class="">(not necessarily a local one) `p: Point` with stored properties</div><div class="">`x`, `y`, and `z`. If it were possible to simultaneously and</div><div class="">independently modify `p` and `p.x`, that would be an enormous</div><div class="">hole in the Law of Exclusivity. So we do need to enforce the</div><div class="">Law somehow here. We have three options.</div><div class=""><br class=""></div><div class="">(This may make more sense after reading the main section</div><div class="">about enforcing the Law.)</div><div class=""><br class=""></div><div class="">The first option is to simply treat `p.x` as also an access to `p`.</div><div class="">This neatly eliminates the hole because whatever enforcement</div><div class="">we're using for `p` will naturally prevent conflicting accesses</div><div class="">to it. But this will also prevent accesses to different</div><div class="">properties from overlapping, because each will cause an access</div><div class="">to `p`, triggering the enforcement.</div><div class=""><br class=""></div><div class="">The other two options involve reversing that relationship.</div><div class="">We could split enforcement out for all the individual stored</div><div class="">properties, not for the aggregate: an access to `p` would be</div><div class="">treated as an access to `p.x`, `p.y`, and `p.z`. Or we could</div><div class="">parameterize enforcement and teach it to record the specific</div><div class="">path of properties being accessed: "", ".x", and so on.</div><div class="">Unfortunately, there are two problems with these schemes.</div><div class="">The first is that we don't always know the full set of</div><div class="">properties, or which properties are stored; the implementation</div><div class="">of a type might be opaque to us due to e.g. generics or</div><div class="">resilience. An access to a computed property must be treated</div><div class="">as an access to the whole value because it involves passing</div><div class="">the variable to a getter or setter either `inout` or `shared`;</div><div class="">thus it does actually conflict with all other properties.</div><div class="">Attempting to make things work despite that by using dynamic</div><div class="">information would introduce ubiquitous bookkeeping into</div><div class="">value-type accessors, endangering the core design goal of</div><div class="">value types that they serve as a low-cost abstraction tool.</div><div class="">The second is that, while these schemes can be applied to</div><div class="">static enforcement relatively easily, applying them to</div><div class="">dynamic enforcement would require a fiendish amount of</div><div class="">bookkeeping to be carried out dynamically; this is simply</div><div class="">not compatible with our performance goals.</div><div class=""><br class=""></div><div class="">Thus, while there is a scheme which allows independent access</div><div class="">to different properties of the same aggregate value, it</div><div class="">requires us to be using static enforcement for the aggregate</div><div class="">access and to know that both properties are stored. This is an</div><div class="">important special case, but it is just a special case.</div><div class="">In all other cases, we must fall back on the general rule</div><div class="">that an access to a property is also an access to the aggregate.</div><div class=""><br class=""></div><div class="">These considerations do not apply to `static` properties and</div><div class="">properties of reference types. There are no language constructs</div><div class="">in Swift which access every property of a class simultaneously,</div><div class="">and it doesn't even make sense to talk about "every" `static`</div><div class="">property of a type because an arbitrary module can add a new</div><div class="">one at any time.</div><div class=""><br class=""></div><div class="">#### Idioms of independent access</div><div class=""><br class=""></div><div class="">The second relates to user expectations.</div><div class=""><br class=""></div><div class="">Preventing overlapping accesses to different properties of a</div><div class="">value type is at most a minor inconvenience. The Law of Exclusivity</div><div class="">prevents "spooky action at a distance" with value types anyway:</div><div class="">for example, calling a method on a variable cannot kick off a</div><div class="">non-obvious sequence of events which eventually reach back and</div><div class="">modify the original variable, because that would involve two</div><div class="">conflicting and overlapping accesses to the same variable.</div><div class=""><br class=""></div><div class="">In contrast, many established patterns with reference types</div><div class="">depend on exactly that kind of notification-based update. In</div><div class="">fact, it's not uncommon in UI code for different properties of</div><div class="">the same object to be modified concurrently: one by the UI and</div><div class="">the other by some background operation. Preventing independent</div><div class="">access would break those idioms, which is not acceptable.</div><div class=""><br class=""></div><div class="">As for `static` properties, programmers expect them to be</div><div class="">independent global variables; it would make no sense for</div><div class="">an access to one global to prevent access to another.</div><div class=""><br class=""></div><div class="">#### Independence and the optimizer</div><div class=""><br class=""></div><div class="">The third relates to the optimization potential of properties.</div><div class=""><br class=""></div><div class="">Part of the purpose of the Law of Exclusivity is that it</div><div class="">allows a large class of optimizations on values. For example,</div><div class="">a non-`mutating` method on a value type can assume that `self`</div><div class="">remains exactly the same for the duration of the method. It</div><div class="">does not have to worry that an unknown function it calls</div><div class="">in the middle will somehow reach back and modify `self`,</div><div class="">because that modification would violate the Law. Even in a</div><div class="">`mutating` method, no code can access `self` unless the</div><div class="">method knows about it. Those assumptions are extremely</div><div class="">important for optimizing Swift code.</div><div class=""><br class=""></div><div class="">However, these assumptions simply cannot be done in general</div><div class="">for the contents of global variables or reference-type</div><div class="">properties. Class references can be shared arbitrarily,</div><div class="">and the optimizer must assume that an unknown function</div><div class="">might have access to the same instance. And any code in</div><div class="">the system can potentially access a global variable (ignoring</div><div class="">access control). So the language implementation would</div><div class="">gain little to nothing from treating accesses to different</div><div class="">properties as non-independent.</div><div class=""><br class=""></div><div class="">#### Subscripts</div><div class=""><br class=""></div><div class="">Much of this discussion also applies to subscripts, though</div><div class="">in the language today subscripts are never technically stored.</div><div class="">Accessing a component of a value type through a subscript</div><div class="">is treated as accessing the entire value, and so is considered</div><div class="">to overlap any other access to the value. The most important</div><div class="">consequence of this is that two different array elements cannot</div><div class="">be simultaneously accessed. This will interfere with certain</div><div class="">common idioms for working with arrays, although some cases</div><div class="">(like concurrently modifying different slices of an array)</div><div class="">are already quite problematic in Swift. We believe that we</div><div class="">can mitigate the majority of the impact here with targetted</div><div class="">improvements to the collection APIs.</div><div class=""><br class=""></div><div class="">## Enforcing the Law of Exclusivity</div><div class=""><br class=""></div><div class="">There are three available mechanisms for enforcing the Law of</div><div class="">Exclusivity: static, dynamic, and undefined. The choice</div><div class="">of mechanism must be decidable by a simple inspection of the</div><div class="">storage declaration, because the definition and all of its</div><div class="">direct accessors must agree on how it is done. Generally,</div><div class="">it will be decided by the kind of storage being declared,</div><div class="">its container (if any), and any attributes that might be</div><div class="">present.</div><div class=""><br class=""></div><div class="">### Static enforcement</div><div class=""><br class=""></div><div class="">Under static enforcement, the compiler detects that the</div><div class="">law is being violated and reports an error. This is the</div><div class="">preferred mechanism where possible because it is safe, reliable,</div><div class="">and imposes no runtime costs.</div><div class=""><br class=""></div><div class="">This mechanism can only be used when it is perfectly decidable.</div><div class="">For example, it can be used for value-type properties because</div><div class="">the Law, recursively applied, ensures that the base storage is</div><div class="">being exclusively accessed. It cannot be used for ordinary</div><div class="">reference-type properties because there is no way to prove in</div><div class="">general that a particular object reference is the unique</div><div class="">reference to an object. However, if we supported</div><div class="">uniquely-referenced class types, it could be used for their</div><div class="">properties.</div><div class=""><br class=""></div><div class="">In some cases, where desired, the compiler may be able to</div><div class="">preserve source compatibility and avoid an error by implicitly</div><div class="">inserting a copy instead. This likely something we would only</div><div class="">do in a source-compatibility mode.</div><div class=""><br class=""></div><div class="">Static enforcement will be used for:</div><div class=""><br class=""></div><div class="">- immutable variables of all kinds,</div><div class=""><br class=""></div><div class="">- local variables, except as affected by the use of closures</div><div class=""> (see below),</div><div class=""><br class=""></div><div class="">- `inout` arguments, and</div><div class=""><br class=""></div><div class="">- instance properties of value types.</div><div class=""><br class=""></div><div class="">### Dynamic enforcement</div><div class=""><br class=""></div><div class="">Under dynamic enforcement, the implementation will maintain</div><div class="">a record of whether each variable is currently being accessed.</div><div class="">If a conflict is detected, it will trigger a dynamic failure.</div><div class="">The compiler may emit an error statically if it detects that</div><div class="">dynamic enforcement will always detect a conflict.</div><div class=""><br class=""></div><div class="">The bookkeeping requires two bits per variable, using a tri-state</div><div class="">of "unaccessed", "read", and "modified". Although multiple</div><div class="">simultaneous reads can be active at once, a full count can be</div><div class="">avoided by saving the old state across the access, with a little</div><div class="">cleverness.</div><div class=""><br class=""></div><div class="">The bookkeeping is intended to be best-effort. It should reliably</div><div class="">detect deterministic violations. It is not required to detect</div><div class="">race conditions; it often will, and that's good, but it's not</div><div class="">required to. It *is* required to successfully handle the case</div><div class="">of concurrent reads without e.g. leaving the bookkeeping record</div><div class="">permanently in the "read" state. But it is acceptable for the</div><div class="">concurrent-reads case to e.g. leave the bookkeeping record in</div><div class="">the "unaccessed" case even if there are still active readers;</div><div class="">this permits the bookkeeping to use non-atomic operations.</div><div class="">However, atomic operations would have to be used if the bookkeeping</div><div class="">records were packed into a single byte for, say, different</div><div class="">properties of a class, because concurrent accesses are</div><div class="">allowed on different variables within a class.</div><div class=""><br class=""></div><div class="">When the compiler detects that an access is "instantaneous",</div><div class="">in the sense that none of the code executed during the access</div><div class="">can possibly cause a re-entrant access to the same variable,</div><div class="">it can avoid updating the bookkeeping record and instead just</div><div class="">check that it has an appropriate value. This is common for</div><div class="">reads, which will often simply copy the value during the access.</div><div class="">When the compiler detects that all possible accesses are</div><div class="">instantaneous, e.g. if the variable is `private` or `internal`,</div><div class="">it can eliminate all bookkeeping. We expect this to be fairly</div><div class="">common.</div><div class=""><br class=""></div><div class="">Dynamic enforcement will be used for:</div><div class=""><br class=""></div><div class="">- local variables, when necessary due to the use of closures</div><div class=""> (see below),</div><div class=""><br class=""></div><div class="">- instance properties of class types,</div><div class=""><br class=""></div><div class="">- `static` and `class` properties, and</div><div class=""><br class=""></div><div class="">- global variables.</div><div class=""><br class=""></div><div class="">We should provide an attribute to allow dynamic enforcement</div><div class="">to be downgraded to undefined enforcement for a specific</div><div class="">property or class. It is likely that some clients will find</div><div class="">the performance consequences of dynamic enforcement to be</div><div class="">excessive, and it will be important to provide them an opt-out.</div><div class="">This will be especially true in the early days of the feature,</div><div class="">while we're still exploring implementation alternatives and</div><div class="">haven't yet implemented any holistic optimizations.</div><div class=""><br class=""></div><div class="">Future work on isolating class instances may allow us to</div><div class="">use static enforcement for some class instance properties.</div><div class=""><br class=""></div><div class="">### Undefined enforcement</div><div class=""><br class=""></div><div class="">Undefined enforcement means that conflicts are not detected</div><div class="">either statically or dynamically, and instead simply have</div><div class="">undefined behavior. This is not a desireable mechanism</div><div class="">for ordinary code given Swift's "safe by default" design,</div><div class="">but it's the only real choice for things like unsafe pointers.</div><div class=""><br class=""></div><div class="">Undefined enforcement will be used for:</div><div class=""><br class=""></div><div class="">- the `memory` properties of unsafe pointers.</div><div class=""><br class=""></div><div class="">### Enforcement for local variables captured by closures</div><div class=""><br class=""></div><div class="">Our ability to statically enforce the Law of Exclusivity</div><div class="">relies on our ability to statically reason about where</div><div class="">uses occur. This analysis is usually straightforward for a</div><div class="">local variable, but it becomes complex when the variable is</div><div class="">captured in a closure because the control flow leading to</div><div class="">the use can be obscured. A closure can potentially be</div><div class="">executed re-entrantly or concurrently, even if it's known</div><div class="">not to escape. The following principles apply:</div><div class=""><br class=""></div><div class="">- If a closure `C` potentially escapes, then for any variable</div><div class=""> `V` captured by `C`, all accesses to `V` potentially executed</div><div class=""> after a potential escape (including the accesses within `C`</div><div class=""> itself) must use dynamic enforcement unless all such acesses</div><div class=""> are reads.</div><div class=""><br class=""></div><div class="">- If a closure `C` does not escape a function, then its</div><div class=""> use sites within the function are known; at each, the closure</div><div class=""> is either directly called or used as an argument to another</div><div class=""> call. Consider the set of non-escaping closures used at</div><div class=""> each such call. For each variable `V` captured by `C`, if</div><div class=""> any of those closures contains a write to `V`, all accesses</div><div class=""> within those closures must use dynamic enforcement, and</div><div class=""> the call is treated for purposes of static enforcement</div><div class=""> as if it were a write to `V`; otherwise, the accesses may use</div><div class=""> static enforcement, and the call is treated as if it were a</div><div class=""> read of `V`.</div><div class=""><br class=""></div><div class="">It is likely that these rules can be improved upon over time.</div><div class="">For example, we should be able to improve on the rule for</div><div class="">direct calls to closures.</div><div class=""><br class=""></div><div class="">## Explicit tools for ownership</div><div class=""><br class=""></div><div class="">### Shared values</div><div class=""><br class=""></div><div class="">A lot of the discussion in this section involves the new concept</div><div class="">of a *shared value*. As the name suggests, a shared value is a</div><div class="">value that has been shared with the current context by another</div><div class="">part of the program that owns it. To be consistent with the</div><div class="">Law of Exclusivity, because multiple parts of the program can</div><div class="">use the value at once, it must be read-only in all of them</div><div class="">(even the owning context). This concept allows programs to</div><div class="">abstract over values without copying them, just like `inout`</div><div class="">allows programs to abstract over variables.</div><div class=""><br class=""></div><div class="">(Readers familiar with Rust will see many similarities between</div><div class="">shared values and Rust's concept of an immutable borrow.)</div><div class=""><br class=""></div><div class="">When the source of a shared value is a storage reference, the</div><div class="">shared value acts essentially like an immutable reference</div><div class="">to that storage. The storage is accessed as a read for the</div><div class="">duration of the shared value, so the Law of Exclusivity</div><div class="">guarantees that no other accesses will be able to modify the</div><div class="">original variable during the access. Some kinds of shared</div><div class="">value may also bind to temporary values (i.e. an r-value).</div><div class="">Since temporary values are always owned by the current</div><div class="">execution context and used in one place, this poses no</div><div class="">additional semantic concerns.</div><div class=""><br class=""></div><div class="">A shared value can be used in the scope that binds it</div><div class="">just like an ordinary parameter or `let` binding.</div><div class="">If the shared value is used in a place that requires</div><div class="">ownership, Swift will simply implicitly copy the value —</div><div class="">again, just like an ordinary parameter or `let` binding.</div><div class=""><br class=""></div><div class="">#### Limitations of shared values</div><div class=""><br class=""></div><div class="">This section of the document describes several ways to form</div><div class="">and use shared values. However, our current design does not</div><div class="">provide general, "first-class" mechanisms for working with them.</div><div class="">A program cannot return a shared value, construct an array</div><div class="">of shared values, store shared values into `struct` fields,</div><div class="">and so on. These limitations are similar to the existing</div><div class="">limitations on `inout` references. In fact, the similarities</div><div class="">are so common that it will be useful to have a term that</div><div class="">encompasses both: we will call them *ephemerals*.</div><div class=""><br class=""></div><div class="">The fact that our design does not attempt to provide first-class</div><div class="">facilities for ephemerals is a well-considered decision,</div><div class="">born from a trio of concerns:</div><div class=""><br class=""></div><div class="">- We have to scope this proposal to something that can</div><div class=""> conceivably be implemented in the coming months. We expect this</div><div class=""> proposal to yield major benefits to the language and its</div><div class=""> implementaton, but it is already quite broad and aggressive.</div><div class=""> First-class ephemerals would add enough complexity to the</div><div class=""> implementation and design that they are clearly out of scope.</div><div class=""> Furthermore, the remaining language-design questions are</div><div class=""> quite large; several existing languages have experimented</div><div class=""> with first-class ephemerals, and the results haven't been</div><div class=""> totally satisfactory.</div><div class=""><br class=""></div><div class="">- Type systems trade complexity for expressivity.</div><div class=""> You can always accept more programs by making the type</div><div class=""> system more sophisticated, but that's not always a good</div><div class=""> trade-off. The lifetime-qualification systems behind</div><div class=""> first-class references in languages like Rust add a lot</div><div class=""> of complexity to the user model. That complexity has real</div><div class=""> costs for users. And it's still inevitably necessary</div><div class=""> to sometimes drop down to unsafe code to work around the</div><div class=""> limitations of the ownership system. Given that a line</div><div class=""> does have to drawn somewhere, it's not completely settled</div><div class=""> that lifetime-qualification systems deserve to be on the</div><div class=""> Swift side of the line.</div><div class=""><br class=""></div><div class="">- A Rust-like lifetime system would not necessarily be</div><div class=""> as powerful in Swift as it is in Rust. Swift intentionally</div><div class=""> provides a language model which reserves a lot of</div><div class=""> implementation flexibility to both the authors of types</div><div class=""> and to the Swift compiler itself.</div><div class=""><br class=""></div><div class=""> For example, polymorphic storage is quite a bit more</div><div class=""> flexible in Swift than it is in Rust. A</div><div class=""> `MutableCollection` in Swift is required to implement a</div><div class=""> `subscript` that provides accessor to an element for an index,</div><div class=""> but the implementation can satisfy this pretty much any way</div><div class=""> it wants. If generic code accesses this `subscript`, and it</div><div class=""> happens to be implemented in a way that provides direct access</div><div class=""> to the underlying memory, then the access will happen in-place;</div><div class=""> but if the `subscript` is implemented with a computed getter</div><div class=""> and setter, then the access will happen in a temporary</div><div class=""> variable and the getter and setter will be called as necessary.</div><div class=""> This only works because Swift's access model is highly</div><div class=""> lexical and maintains the ability to run arbitrary code</div><div class=""> at the end of an access. Imagine what it would take to</div><div class=""> implement a loop that added these temporary mutable</div><div class=""> references to an array — each iteration of the loop would</div><div class=""> have to be able to queue up arbitrary code to run as a clean-up</div><div class=""> when the function was finished with the array. This would</div><div class=""> hardly be a low-cost abstraction! A more Rust-like</div><div class=""> `MutableCollection` interface that worked within the</div><div class=""> lifetime rules would have to promise that the `subscript`</div><div class=""> returned a pointer to existing memory; and that wouldn't</div><div class=""> allow a computed implementation at all.</div><div class=""><br class=""></div><div class=""> A similar problem arises even with simple `struct` members.</div><div class=""> The Rust lifetime rules say that, if you have a pointer to</div><div class=""> a `struct`, you can make a pointer to a field of that `struct`</div><div class=""> and it'll have the same lifetime as the original pointer.</div><div class=""> But this assumes not only that the field is actually stored</div><div class=""> in memory, but that it is stored *simply*, such that you can</div><div class=""> form a simple pointer to it and that pointer will obey the</div><div class=""> standard ABI for pointers to that type. This means that</div><div class=""> Rust cannot use layout optimizations like packing boolean</div><div class=""> fields together in a byte or even just decreasing the</div><div class=""> alignment of a field. This is not a guarantee that we are</div><div class=""> willing to make in Swift.</div><div class=""><br class=""></div><div class="">For all of these reasons, while we remain theoretically</div><div class="">interested in exploring the possibilities of a more</div><div class="">sophisticated system that would allow broader uses of</div><div class="">ephemerals, we are not proposing to take that on now. Since</div><div class="">such a system would primarily consist of changes to the type</div><div class="">system, we are not concerned that this will cause ABI-stability</div><div class="">problems in the long term. Nor are we concerned that we will</div><div class="">suffer from source incompatibilities; we believe that any</div><div class="">enhancements here can be done as extensions and generalizations</div><div class="">of the proposed features.</div><div class=""><br class=""></div><div class="">### Local ephemeral bindings</div><div class=""><br class=""></div><div class="">It is already a somewhat silly limitation that Swift provides</div><div class="">no way to abstract over storage besides passing it as an</div><div class="">`inout` argument. It's an easy limitation to work around,</div><div class="">since programmers who want a local `inout` binding can simply</div><div class="">introduce a closure and immediately call it, but that's an</div><div class="">awkward way of achieving something that ought to be fairly easy.</div><div class=""><br class=""></div><div class="">Shared values make this limitation even more apparent, because</div><div class="">a local shared value is an interesting alternative to a local `let`:</div><div class="">it avoids a copy at the cost of preventing other accesses to</div><div class="">the original storage. We would not encourage programmers to</div><div class="">use `shared` instead of `let` throughout their code, especially</div><div class="">because the optimizer will often be able to eliminate the copy</div><div class="">anyway. However, the optimizer cannot always remove the copy,</div><div class="">and so the `shared` micro-optimization can be useful in select</div><div class="">cases. Furthermore, eliminating the formal copy may also be</div><div class="">semantically necessary when working with non-copyable types.</div><div class=""><br class=""></div><div class="">We propose to remove this limitation in a straightforward way:</div><div class=""><br class=""></div><div class="">```</div><div class=""> inout root = &tree.root</div><div class=""><br class=""></div><div class=""> shared elements = self.queue</div><div class="">```</div><div class=""><br class=""></div><div class="">The initializer is required and must be a storage reference</div><div class="">expression. The access lasts for the remainder of the scope.</div><div class=""><br class=""></div><div class="">### Function parameters</div><div class=""><br class=""></div><div class="">Function parameters are the most important way in which</div><div class="">programs abstract over values. Swift currently provides</div><div class="">three kinds of argument-passing:</div><div class=""><br class=""></div><div class="">- Pass-by-value, owned. This is the rule for ordinary</div><div class=""> arguments. There is no way to spell this explicitly.</div><div class=""><br class=""></div><div class="">- Pass-by-value, shared. This is the rule for the `self`</div><div class=""> arguments of `nonmutating` methods. There is no way to</div><div class=""> spell this explicitly.</div><div class=""><br class=""></div><div class="">- Pass-by-reference. This is the rule used for `inout`</div><div class=""> arguments and the `self` arguments of `mutating` methods.</div><div class=""><br class=""></div><div class="">Our proposal here is just to allow the non-standard</div><div class="">cases to be spelled explicitly:</div><div class=""><br class=""></div><div class="">- A function argument can be explicitly declared `owned`:</div><div class=""><br class=""></div><div class=""> ```</div><div class=""> func append(_ values: owned [Element]) {</div><div class=""> ...</div><div class=""> }</div><div class=""> ```</div><div class=""><br class=""></div><div class=""> This cannot be combined with `shared` or `inout`.</div><div class=""><br class=""></div><div class=""> This is just an explicit way of writing the default, and</div><div class=""> we do not expect that users will write it often unless</div><div class=""> they're working with non-copyable types.</div><div class=""><br class=""></div><div class="">- A function argument can be explicitly declared `shared`.</div><div class=""><br class=""></div><div class=""> ```</div><div class=""> func ==(left: shared String, right: shared String) -> Bool {</div><div class=""> ...</div><div class=""> }</div><div class=""> ```</div><div class=""><br class=""></div><div class=""> This cannot be combined with `owned` or `inout`.</div><div class=""><br class=""></div><div class=""> If the function argument is a storage reference expression,</div><div class=""> that storage is accessed as a read for the duration of the</div><div class=""> call. Otherwise, the argument expression is evaluated as</div><div class=""> an r-value and that temporary value is shared for the call.</div><div class=""> It's important to allow temporary values to be shared for</div><div class=""> function arguments because many function parameters will be</div><div class=""> marked as `shared` simply because the functions don't</div><div class=""> actually from owning that parameter, not because it's in</div><div class=""> any way semantically important that they be passed a</div><div class=""> reference to an existing variable. For example, we expect</div><div class=""> to change things like comparison operators to take their</div><div class=""> parameters `shared`, because it needs to be possible to</div><div class=""> compare non-copyable values without claiming them, but</div><div class=""> this should not prevent programmers from comparing things</div><div class=""> to literal values.</div><div class=""><br class=""></div><div class=""> Like `inout`, this is part of the function type. Unlike</div><div class=""> `inout`, most function compatibility checks (such as override</div><div class=""> and function conversion checking) should succeed with a</div><div class=""> `shared` / `owned` mismatch. If a function with an `owned`</div><div class=""> parameter is converted to (or overrides) a function with a</div><div class=""> `shared` parameter, the argument type must actually be</div><div class=""> copyable.</div><div class=""><br class=""></div><div class="">- A method can be explicitly declared `consuming`.</div><div class=""><br class=""></div><div class=""> ```</div><div class=""> consuming func moveElements(into collection: inout [Element]) {</div><div class=""> ...</div><div class=""> }</div><div class=""> ```</div><div class=""><br class=""></div><div class=""> This causes `self` to be passed as an owned value and therefore</div><div class=""> cannot be combined with `mutating` or `nonmutating`.</div><div class=""><br class=""></div><div class=""> `self` is still an immutable binding within the method.</div><div class=""><br class=""></div><div class="">### Function results</div><div class=""><br class=""></div><div class="">As discussed at the start of this section, Swift's lexical</div><div class="">access model does not extend well to allowing ephemerals</div><div class="">to be returned from functions. Performing an access requires</div><div class="">executing storage-specific code at both the beginning and</div><div class="">the end of the access. After a function returns, it has no</div><div class="">further ability to execute code.</div><div class=""><br class=""></div><div class="">We could, conceivably, return a callback along with the</div><div class="">ephemeral, with the expectation that the callback will be</div><div class="">executed when the caller is done with the ephemeral.</div><div class="">However, this alone would not be enough, because the callee</div><div class="">might be relying on guarantees from its caller. For example,</div><div class="">considering a `mutating` method on a `struct` which wants</div><div class="">to returns an `inout` reference to a stored property. The</div><div class="">correctness of this depends not only on the method being able</div><div class="">to clean up after the access to the property, but on the</div><div class="">continued validity of the variable to which `self` was bound.</div><div class="">What we really want is to maintain the current context in the</div><div class="">callee, along with all the active scopes in the caller, and</div><div class="">simply enter a new nested scope in the caller with the</div><div class="">ephemeral as a sort of argument. But this is a well-understood</div><div class="">situation in programming languages: it is just a kind of</div><div class="">co-routine. (Because of the scoping restrictions, it can</div><div class="">also be thought of as sugar for a callback function in</div><div class="">which `return`, `break`, etc. actually work as expected.)</div><div class=""><br class=""></div><div class="">In fact, co-routines are useful for solving a number of</div><div class="">problems relating to ephemerals. We will explore this</div><div class="">idea in the next few sub-sections.</div><div class=""><br class=""></div><div class="">### `for` loops</div><div class=""><br class=""></div><div class="">In the same sense that there are three interesting ways of</div><div class="">passing an argument, we can identify three interesting styles</div><div class="">of iterating over a sequence. Each of these can be expressed</div><div class="">with a `for` loop.</div><div class=""><br class=""></div><div class="">#### Consuming iteration</div><div class=""><br class=""></div><div class="">The first iteration style is what we're already familiar with</div><div class="">in Swift: a consuming iteration, where each step is presented</div><div class="">with an owned value. This is the only way we can iterate over</div><div class="">an arbitrary sequence where the values might be created on demand.</div><div class="">It is also important for working with collections of non-copyable</div><div class="">types because it allows the collection to be destructured and the</div><div class="">loop to take ownership of the elements. Because it takes ownership</div><div class="">of the values produced by a sequence, and because an arbitrary</div><div class="">sequence cannot be iterated multiple times, this is a</div><div class="">`consuming` operation on `Sequence`.</div><div class=""><br class=""></div><div class="">This can be explicitly requested by declaring the iteration</div><div class="">variable `owned`:</div><div class=""><br class=""></div><div class="">```</div><div class=""> for owned employee in company.employees {</div><div class=""> newCompany.employees.append(employee)</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">It is also used implicitly when the requirements for a</div><div class="">non-mutating iteration are not met. (Among other things,</div><div class="">this is necessary for source compatibility.)</div><div class=""><br class=""></div><div class="">The next two styles make sense only for collections.</div><div class=""><br class=""></div><div class="">#### Non-mutating iteration</div><div class=""><br class=""></div><div class="">A non-mutating iteration simply visits each of the elements</div><div class="">in the collection, leaving it intact and unmodified. We have</div><div class="">no reason to copy the elements; the iteration variable can</div><div class="">simply be bound to a shared value. This is a `nonmutating`</div><div class="">operaton on `Collection`.</div><div class=""><br class=""></div><div class="">This can be explicitly requested by declaring the iteration</div><div class="">variable `shared`:</div><div class=""><br class=""></div><div class="">```</div><div class=""> for shared employee in company.employees {</div><div class=""> if !employee.respected { throw CatastrophicHRFailure() }</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">It is also used by default when the sequence type is known to</div><div class="">conform to `Collection`, since this is the optimal way of</div><div class="">iterating over a collection.</div><div class=""><br class=""></div><div class="">```</div><div class=""> for employee in company.employees {</div><div class=""> if !employee.respected { throw CatastrophicHRFailure() }</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">If the sequence operand is a storage reference expression,</div><div class="">the storage is accessed for the duration of the loop. Note</div><div class="">that this means that the Law of Exclusivity will implicitly</div><div class="">prevent the collection from being modified during the</div><div class="">iteration. Programs can explicitly request an iteration</div><div class="">over a copy of the value in that storage by using the `copy`</div><div class="">intrinsic function on the operand.</div><div class=""><br class=""></div><div class="">#### Mutating iteration</div><div class=""><br class=""></div><div class="">A mutating iteration visits each of the elements and</div><div class="">potentially changes it. The iteration variable is an</div><div class="">`inout` reference to the element. This is a `mutating`</div><div class="">operation on `MutableCollection`.</div><div class=""><br class=""></div><div class="">This must be explicitly requested by declaring the</div><div class="">iteration variable `inout`:</div><div class=""><br class=""></div><div class="">```</div><div class=""> for inout employee in company.employees {</div><div class=""> employee.respected = true</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">The sequence operand must be a storage reference expression.</div><div class="">The storage will be accessed for the duraton of the loop,</div><div class="">which (as above) will prevent any other overlapping accesses</div><div class="">to the collection. (But this rule does not apply if the</div><div class="">collection type defines the operation as a non-mutating</div><div class="">operation, which e.g. a reference-semantics collection might.)</div><div class=""><br class=""></div><div class="">#### Expressing mutating and non-mutating iteration</div><div class=""><br class=""></div><div class="">Mutating and non-mutating iteration require the collection</div><div class="">to produce ephemeral values at each step. There are several</div><div class="">ways we could express this in the language, but one reasonable</div><div class="">approach would be to use co-routines. Since a co-routine does</div><div class="">not abandon its execution context when yielding a value to its</div><div class="">caller, it is reasonable to allow a co-routine to yield</div><div class="">multiple times, which corresponds very well to the basic</div><div class="">code pattern of a loop. This produces a kind of co-routine</div><div class="">often called a generator, which is used in several major</div><div class="">languages to conveniently implement iteration. In Swift,</div><div class="">to follow this pattern, we would need to allow the definition</div><div class="">of generator functions, e.g.:</div><div class=""><br class=""></div><div class="">```</div><div class=""> mutating generator iterateMutable() -> inout Element {</div><div class=""> var i = startIndex, e = endIndex</div><div class=""> while i != e {</div><div class=""> yield &self[i]</div><div class=""> self.formIndex(after: &i)</div><div class=""> }</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">On the client side, it is clear how this could be used to</div><div class="">implement `for` loops; what is less clear is the right way to</div><div class="">allow generators to be used directly by code. There are</div><div class="">interesting constraints on how the co-routine can be used</div><div class="">here because, as mentioned above, the entire co-routine</div><div class="">must logically execute within the scope of an access to the</div><div class="">base value. If, as is common for generators, the generator</div><div class="">function actually returns some sort of generator object,</div><div class="">the compiler must ensure that that object does not escape</div><div class="">that enclosing access. This is a significant source of</div><div class="">complexity.</div><div class=""><br class=""></div><div class="">### Generalized accessors</div><div class=""><br class=""></div><div class="">Swift today provides very coarse tools for implementing</div><div class="">properties and subscripts: essentially, just `get` and `set`</div><div class="">methods. These tools are inadequate for tasks where</div><div class="">performance is critical because they don't allow direct</div><div class="">access to values without copies. The standard library</div><div class="">has access to a slightly broader set of tools which can</div><div class="">provide such direct access in limited cases, but they're</div><div class="">still quite weak, and we've been reluctant to expose them to</div><div class="">users for a variety of reasons.</div><div class=""><br class=""></div><div class="">Ownership offers us an opportunity to revisit this problem</div><div class="">because `get` doesn't work for collections of non-copyable</div><div class="">types because it returns a value, which must therefore be</div><div class="">owned. The accessor really needs to be able to yield a</div><div class="">shared value instead of returning an owned one. Again,</div><div class="">one reasonable approach for allowing this is to use a</div><div class="">special kind of co-routine. Unlike a generator, this</div><div class="">co-routine would be required to yield exactly once.</div><div class="">And there is no need to design an explicit way for programmers</div><div class="">to invoke one because these would only be used in accessors.</div><div class=""><br class=""></div><div class="">The idea is that, instead of defining `get` and `set`,</div><div class="">a storage declaration could define `read` and `modify`:</div><div class=""><br class=""></div><div class="">```</div><div class=""> var x: String</div><div class=""> var y: String</div><div class=""> var first: String {</div><div class=""> read {</div><div class=""> if x < y { yield x }</div><div class=""> else { yield y }</div><div class=""> }</div><div class=""> modify {</div><div class=""> if x < y { yield &x }</div><div class=""> else { yield &y }</div><div class=""> }</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">A storage declaration must define either a `get` or a `read`</div><div class="">(or be a stored property), but not both.</div><div class=""><br class=""></div><div class="">To be mutable, a storage declaration must also define either a</div><div class="">`set` or a `modify`. It may also choose to define *both*, in</div><div class="">which case `set` will be used for assignments and `modify` will</div><div class="">be used for modifications. This is useful for optimizing</div><div class="">certain complex computed properties because it allows modifications</div><div class="">to be done in-place without forcing simple assignments to first</div><div class="">read the old value; however, care must be taken to ensure that</div><div class="">the `modify` is consistent in behavior with the `get` and the</div><div class="">`set`.</div><div class=""><br class=""></div><div class="">### Intrinsic functions</div><div class=""><br class=""></div><div class="">#### `move`</div><div class=""><br class=""></div><div class="">The Swift optimizer will generally try to move values around</div><div class="">instead of copying them, but it can be useful to force its hand.</div><div class="">For this reason, we propose the `move` function. Conceptually,</div><div class="">`move` is simply a top-level function in the Swift standard</div><div class="">library:</div><div class=""><br class=""></div><div class="">```</div><div class=""> func move<T>(_ value: T) -> T {</div><div class=""> return value</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">However, it is blessed with some special semantics. It cannot</div><div class="">be used indirectly. The argument expression must be a reference</div><div class="">to some kind of local owning storage: either a `let`, a `var`,</div><div class="">or an `inout` binding. A call to `move` is evaluated by</div><div class="">semantically moving the current value out of the argument</div><div class="">variable and returning it as the type of the expression,</div><div class="">leaving the variable uninitialized for the purposes of the</div><div class="">definitive-initialization analysis. What happens with the</div><div class="">variable next depends on the kind of variable:</div><div class=""><br class=""></div><div class="">- A `var` simply transitions back to being uninitialized.</div><div class=""> Uses of it are illegal until it is assigned a new value and</div><div class=""> thus reinitialized.</div><div class=""><br class=""></div><div class="">- An `inout` binding is just like a `var`, except that it is</div><div class=""> illegal for it to go out of scope uninitialized. That is,</div><div class=""> if a program moves out of an `inout` binding, the program</div><div class=""> must assign a new value to it before it can exit the scope</div><div class=""> in any way (including by throwing an error). Note that the</div><div class=""> safety of leaving an `inout` temporarily uninitialized</div><div class=""> depends on the Law of Exclusivity.</div><div class=""><br class=""></div><div class="">- A `let` cannot be reinitialized and so cannot be used</div><div class=""> again at all.</div><div class=""><br class=""></div><div class="">This should be a straightforward addition to the existing</div><div class="">definitive-initialization analysis, which proves that local</div><div class="">variables are initialized before use.</div><div class=""><br class=""></div><div class="">#### `copy`</div><div class=""><br class=""></div><div class="">`copy` is a top-level function in the Swift standard library:</div><div class=""><br class=""></div><div class="">```</div><div class=""> func copy<T>(_ value: T) -> T {</div><div class=""> return value</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">The argument must be a storage reference expression. The</div><div class="">semantics are exactly as given in the above code: the argument</div><div class="">value is returned. This is useful for several reasons:</div><div class=""><br class=""></div><div class="">- It suppresses syntactic special-casing. For example, as</div><div class=""> discussed above, if a `shared` argument is a storage</div><div class=""> reference, that storage is normally accessed for the duration</div><div class=""> of the call. The programmer can suppress this and force the</div><div class=""> copy to complete before the call by calling `copy` on the</div><div class=""> storage reference before </div><div class=""><br class=""></div><div class="">- It is necessary for types that have suppressed implicit</div><div class=""> copies. See the section below on non-copyable types.</div><div class=""><br class=""></div><div class="">#### `endScope`</div><div class=""><br class=""></div><div class="">`endScope` is a top-level function in the Swift standard library:</div><div class=""><br class=""></div><div class="">```</div><div class=""> func endScope<T>(_ value: T) -> () {}</div><div class="">```</div><div class=""><br class=""></div><div class="">The argument must be a reference to a local `let`, `var`, or</div><div class="">standalone (non-parameter, non-loop) `inout` or `shared`</div><div class="">declaration. If it's a `let` or `var`, the variable is</div><div class="">immediately destroyed. If it's an `inout` or `shared`,</div><div class="">the access immediately ends.</div><div class=""><br class=""></div><div class="">The definitive-initialization analysis must prove that</div><div class="">the declaration is not used after this call. It's an error</div><div class="">if the storage is a `var` that's been captured in an escaping</div><div class="">closure.</div><div class=""><br class=""></div><div class="">This is useful for ending an access before control reaches the</div><div class="">end of a scope, as well as for micro-optimizing the destruction</div><div class="">of values.</div><div class=""><br class=""></div><div class="">`endScope` provides a guarantee that the given variable has</div><div class="">been destroyed, or the given access has ended, by the time</div><div class="">of the execution of the call. It does not promise that these</div><div class="">things happen exactly at that point: the implementation is</div><div class="">still free to end them earlier.</div><div class=""><br class=""></div><div class="">### Lenses</div><div class=""><br class=""></div><div class="">Currently, all storage reference expressions in Swift are *concrete*:</div><div class="">every component is statically resolvable to a storage declaration.</div><div class="">There is some recurring interest in the community in allowing programs</div><div class="">to abstract over storage, so that you might say:</div><div class=""><br class=""></div><div class="">```</div><div class=""> let prop = Widget.weight</div><div class="">```</div><div class=""><br class=""></div><div class="">and then `prop` would be an abstract reference to the `weight`</div><div class="">property, and its type would be something like `(Widget) -> Double`.</div><div class=""><br class=""></div><div class="">This feature is relevant to the ownership model because an ordinary</div><div class="">function result must be an owned value: not shared, and not mutable.</div><div class="">This means lenses could only be used to abstract *reads*, not</div><div class="">*writes*, and could only be created for copyable properties. It</div><div class="">also means code using lenses would involve more copies than the</div><div class="">equivalent code using concrete storage references.</div><div class=""><br class=""></div><div class="">Suppose that, instead of being simple functions, lenses were their</div><div class="">own type of value. An application of a lens would be a storage</div><div class="">reference expression, but an *abstract* one which accessed</div><div class="">statically-unknown members. This would require the language</div><div class="">implementation to be able to perform that sort of access</div><div class="">dynamically. However, the problem of accessing an unknown</div><div class="">property is very much like the problem of accessing a known</div><div class="">property whose implementation is unknown; that is, the language</div><div class="">already has to do very similar things in order to implement</div><div class="">generics and resilience.</div><div class=""><br class=""></div><div class="">Overall, such a feature would fit in very neatly with the</div><div class="">ownership model laid out here.</div><div class=""><br class=""></div><div class="">## Non-copyable types</div><div class=""><br class=""></div><div class="">Non-copyable types are useful in a variety of expert situations.</div><div class="">For example, they can be used to efficiently express unique</div><div class="">ownership. They are also interesting for expressing values</div><div class="">that have some sort of independent identity, such as atomic</div><div class="">types. They can also be used as a formal mechanism for</div><div class="">encouraging code to work more efficiently with types that</div><div class="">might be expensive to copy, such as large struct types. The</div><div class="">unifying theme is that we do not want to allow the type to</div><div class="">be copied implicitly.</div><div class=""><br class=""></div><div class="">The complexity of handling non-copyable types in Swift</div><div class="">comes from two main sources:</div><div class=""><br class=""></div><div class="">- The language must provide tools for moving values around</div><div class=""> and sharing them without forcing copies. We've already</div><div class=""> proposed these tools in this document because they're</div><div class=""> equally important for optimizing the use of copyable types.</div><div class=""><br class=""></div><div class="">- The generics system has to be able to express generics over</div><div class=""> non-copyable types without massively breaking source</div><div class=""> compatibility and forcing non-copyable types on everybody.</div><div class=""><br class=""></div><div class="">Otherwise, the feature itself is pretty small. The compiler</div><div class="">implicitly emits moves instead of copies, just like we discussed</div><div class="">above for the `move` intrinsic, and then diagnoses anything</div><div class="">that that didn't work for.</div><div class=""><br class=""></div><div class="">### `moveonly` contexts</div><div class=""><br class=""></div><div class="">The generics problem is real, though. The most obvious way</div><div class="">to model copyability in Swift is to have a `Copyable`</div><div class="">protocol which types can conform to. An unconstrained type</div><div class="">parameter `T` would then not be assumed to be copyable.</div><div class="">Unfortunately, this would be a disaster for both source</div><div class="">compatibility and usability, because almost all the existing</div><div class="">generic code written in Swift assumes copyability, and</div><div class="">we really don't want programmers to have to worry about</div><div class="">non-copyable types in their first introduction to generic</div><div class="">code.</div><div class=""><br class=""></div><div class="">Furthermore, we don't want types to have to explicitly</div><div class="">declare conformance to `Copyable`. That should be the</div><div class="">default.</div><div class=""><br class=""></div><div class="">The logical solution is to maintain the default assumption</div><div class="">that all types are copyable, and then allow select contexts</div><div class="">to turn that assumption off. We will cause these contexts</div><div class="">`moveonly` contexts. All contexts lexically nested within</div><div class="">a `moveonly` context are also implicitly `moveonly`.</div><div class=""><br class=""></div><div class="">A type can be a `moveonly` context:</div><div class=""><br class=""></div><div class="">```</div><div class=""> moveonly struct Array<Element> {</div><div class=""> // Element and Array<Element> are not assumed to be copyable here</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">This suppresses the `Copyable` assumption for the type</div><div class="">declared, its generic arguments (if any), and their</div><div class="">hierarchies of associated types.</div><div class=""><br class=""></div><div class="">An extension can be a `moveonly` context:</div><div class=""><br class=""></div><div class="">```</div><div class=""> moveonly extension Array {</div><div class=""> // Element and Array<Element> are not assumed to be copyable here</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">A type can declare conditional copyability using a conditional</div><div class="">conformance:</div><div class=""><br class=""></div><div class="">```</div><div class=""> moveonly extension Array: Copyable where Element: Copyable {</div><div class=""> ...</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">Conformance to `Copyable`, conditional or not, is an</div><div class="">inherent property of a type and must be declared in the</div><div class="">same module that defines the type. (Or possibly even the</div><div class="">same file.)</div><div class=""><br class=""></div><div class="">A non-`moveonly` extension of a type reintroduces the</div><div class="">copyability assumption for the type and its generic</div><div class="">arguments. This is necessary in order to allow standard</div><div class="">library types to support non-copyable elements without</div><div class="">breaking compatibility with existing extensions. If the</div><div class="">type doesn't declare any conformance to `Copyable`, giving</div><div class="">it a non-`moveonly` extension is an error.</div><div class=""><br class=""></div><div class="">A function can be a `moveonly` context:</div><div class=""><br class=""></div><div class="">```</div><div class=""> extension Array {</div><div class=""> moveonly func report<U>(_ u: U)</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">This suppresses the copyability assumption for any new</div><div class="">generic arguments and their hierarchies of associated types.</div><div class=""><br class=""></div><div class="">A lot of the details of `moveonly` contexts are still up</div><div class="">in the air. It is likely that we will need substantial</div><div class="">implementation experience before we can really settle on</div><div class="">the right design here.</div><div class=""><br class=""></div><div class="">One possibility we're considering is that `moveonly`</div><div class="">contexts will also suppress the implicit copyability</div><div class="">assumption for values of copyable types. This would</div><div class="">provide an important optimization tool for code that</div><div class="">needs to be very careful about copies.</div><div class=""><br class=""></div><div class="">### `deinit` for non-copyable types</div><div class=""><br class=""></div><div class="">A value type declared `moveonly` which does not conform</div><div class="">to `Copyable` (even conditionally) may define a `deinit`</div><div class="">method. `deinit` must be defined in the primary type</div><div class="">definition, not an extension.</div><div class=""><br class=""></div><div class="">`deinit` will be called to destroy the value when it is</div><div class="">no longer required. This permits non-copyable types to be</div><div class="">used to express the unique ownership of resources. For</div><div class="">example, here is a simple file-handle type that ensures</div><div class="">that the handle is closed when the value is destroyed:</div><div class=""><br class=""></div><div class="">```</div><div class=""> moveonly struct File {</div><div class=""> var descriptor: Int32</div><div class=""><br class=""></div><div class=""> init(filename: String) throws {</div><div class=""> descriptor = Darwin.open(filename, O_RDONLY)</div><div class=""><br class=""></div><div class=""> // Abnormally exiting 'init' at any point prevents deinit</div><div class=""> // from being called.</div><div class=""> if descriptor == -1 { throw ... }</div><div class=""> }</div><div class=""><br class=""></div><div class=""> deinit {</div><div class=""> _ = Darwin.close(descriptor)</div><div class=""> }</div><div class=""><br class=""></div><div class=""> consuming func close() throws {</div><div class=""> if Darwin.fsync(descriptor) != 0 { throw ... }</div><div class=""><br class=""></div><div class=""> // This is a consuming function, so it has ownership of self.</div><div class=""> // It doesn't consume self in any other way, so it will</div><div class=""> // destroy it when it exits by calling deinit. deinit</div><div class=""> // will then handle actually closing the descriptor.</div><div class=""> }</div><div class=""> }</div><div class="">```</div><div class=""><br class=""></div><div class="">Swift is permitted to destroy a value (and thus call `deinit`)</div><div class="">at any time between its last use and its formal point of</div><div class="">destruction. The exact definition of "use" for the purposes</div><div class="">of this definition is not yet fully decided.</div><div class=""><br class=""></div><div class="">If the value type is a `struct`, `self` can only be used</div><div class="">in `deinit` in order to refer to the stored properties</div><div class="">of the type. The stored properties of `self` are treated</div><div class="">like local `let` constants for the purposes of the</div><div class="">definitive-initialization analysis; that is, they are owned</div><div class="">by the `deinit` and can be moved out of.</div><div class=""><br class=""></div><div class="">If the value type is an `enum`, `self` can only be used</div><div class="">in `deinit` as the operand of a `switch`. Within this</div><div class="">`switch`, any associated values are used to initialize</div><div class="">the corresponding bindings, which take ownership of those</div><div class="">values. Such a `switch` leaves `self` uninitialized.</div><div class=""><br class=""></div><div class="">### Explicitly-copyable types</div><div class=""><br class=""></div><div class="">Another idea in the area of non-copyable types that we're</div><div class="">exploring is the ability to declare that a type cannot</div><div class="">be implicitly copied. For example, a very large struct</div><div class="">can formally be copied, but it might be an outsized</div><div class="">impact on performance if it is copied unnecessarily.</div><div class="">Such a type should conform to `Copyable`, and it should</div><div class="">be possible to request a copy with the `copy` function,</div><div class="">but the compiler should diagnose any implicit copies</div><div class="">the same way that it would diagnose copies of a</div><div class="">non-copyable type.</div><div class=""><br class=""></div><div class="">## Implementation priorities</div><div class=""><br class=""></div><div class="">This document has laid out a large amount of work.</div><div class="">We can summarize it as follows:</div><div class=""><br class=""></div><div class="">- Enforcing the Law of Exclusivity:</div><div class=""><br class=""></div><div class=""> - Static enforcement</div><div class=""> - Dynamic enforcement</div><div class=""> - Optimization of dynamic enforcement</div><div class=""><br class=""></div><div class="">- New annotations and declarations:</div><div class=""><br class=""></div><div class=""> - `shared` parameters</div><div class=""> - `consuming` methods</div><div class=""> - Local `shared` and `inout` declarations</div><div class=""><br class=""></div><div class="">- New intrinsics affecting DI:</div><div class=""><br class=""></div><div class=""> - The `move` function and its DI implications</div><div class=""> - The `endScope` function and its DI implications</div><div class=""><br class=""></div><div class="">- Co-routine features:</div><div class=""><br class=""></div><div class=""> - Generalized accessors</div><div class=""> - Generators</div><div class=""><br class=""></div><div class="">- Non-copyable types</div><div class=""><br class=""></div><div class=""> - Further design work</div><div class=""> - DI enforcement</div><div class=""> - `moveonly` contexts</div><div class=""><br class=""></div><div class="">The single most important goal for the upcoming releases is</div><div class="">ABI stability. The prioritization and analysis of these</div><div class="">features must center around their impact on the ABI. With</div><div class="">that in mind, here are the primary ABI considerations:</div><div class=""><br class=""></div><div class="">The Law of Exclusivity affects the ABI because it</div><div class="">changes the guarantees made for parameters. We must adopt</div><div class="">this rule before locking down on the ABI, or else we will</div><div class="">get stuck making conservative assumptions forever.</div><div class="">However, the details of how it is enforced do not affect</div><div class="">the ABI unless we choose to offload some of the work to the</div><div class="">runtime, which is not necessary and which can be changed</div><div class="">in future releases. (As a technical note, the Law</div><div class="">of Exclusivity is likely to have a major impact on the</div><div class="">optimizer; but this is an ordinary project-scheduling</div><div class="">consideration, not an ABI-affecting one.)</div><div class=""><br class=""></div><div class="">The standard library is likely to enthusiastically adopt</div><div class="">ownership annotations on parameters. Those annotations will</div><div class="">affect the ABI of those library routines. Library</div><div class="">developers will need time in order to do this adoption,</div><div class="">but more importantly, they will need some way to validate</div><div class="">that their annotations are useful. Unfortunately, the best</div><div class="">way to do that validation is to implement non-copyable types,</div><div class="">which are otherwise very low on the priority list.</div><div class=""><br class=""></div><div class="">The generalized accessors work includes changing the standard</div><div class="">set of "most general" accessors for properties and subscripts</div><div class="">from `get`/`set`/`materializeForSet` to (essentially)</div><div class="">`read`/`set`/`modify`. This affects the basic ABI of</div><div class="">all polymorphic property and subscript accesses, so it</div><div class="">needs to happen. However, this ABI change can be done</div><div class="">without actually taking the step of allowing co-routine-style</div><div class="">accessors to be defined in Swift. The important step is</div><div class="">just ensuring that the ABI we've settled on is good</div><div class="">enough for co-routines in the future.</div><div class=""><br class=""></div><div class="">The generators work may involve changing the core collections</div><div class="">protocols. That will certainly affect the ABI. In contrast</div><div class="">with the generalized accessors, we will absolutely need</div><div class="">to implement generators in order to carry this out.</div><div class=""><br class=""></div><div class="">Non-copyable types and algorithms only affect the ABI</div><div class="">inasmuch as they are adopted in the standard library.</div><div class="">If the library is going to extensively adopt them for</div><div class="">standard collections, that needs to happen before we</div><div class="">stabilize the ABI.</div><div class=""><br class=""></div><div class="">The new local declarations and intrinsics do not affect the ABI.</div><div class="">(As is often the case, the work with the fewest implications</div><div class="">is also some of the easiest.)</div><div class=""><br class=""></div><div class="">Adopting ownership and non-copyable types in the standard</div><div class="">library is likely to be a lot of work, but will be important</div><div class="">for the usability of non-copyable types. It would be very</div><div class="">limiting if it was not possible to create an `Array`</div><div class="">of non-copyable types.</div><div class=""><br class=""></div><div class="">(end)</div><div class=""><br class=""></div></body></html>