From 7e767dc26d257a404b7e2642584ef693ffe6c07b Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Wed, 24 Jan 2024 18:16:51 -0800
Subject: [PATCH 01/59] First full draft.

---
 proposals/NNNN-lifetime-dependency.md | 463 ++++++++++++++++++++++++++
 1 file changed, 463 insertions(+)
 create mode 100644 proposals/NNNN-lifetime-dependency.md

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
new file mode 100644
index 0000000000..3e4c6e2b1e
--- /dev/null
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -0,0 +1,463 @@
+# Compile-time Lifetime Dependency Annotations
+
+* Proposal: [SE-NNNN](NNNN-filename.md)
+* Authors: [Andrew Trick](https://github.com/atrick), [Meghana Gupta](https://github.com/meg-gupta), [Tim Kientzle](https://github.com/tbkka)
+* Review Manager: TBD
+* Status: **Awaiting implementation**
+
+## Introduction
+
+We would like to propose extensions to Swift's function-declaration syntax that allow authors to specify lifetime dependencies between the return value and one or more of the arguments.
+These would also be useable with methods that wish to declare a dependency on `self`.
+To reduce the burden of manually adding such annotations, we also propose inferring lifetime dependencies in certain common cases without requiring any additional annotations.
+
+This is a key requirement for the `BufferView` type being discussed elsewhere, and is closely related to the proposal for `~Escapable` types.
+
+#### See Also
+
+* **TODO**: **** Forum thread discussing this proposal
+* [Forum discussion of BufferView language requirements](https://forums.swift.org/t/roadmap-language-support-for-bufferview)
+* [Proposed Vision document for BufferView language requirements (includes description of ~Escapable)](https://github.com/atrick/swift-evolution/blob/fd63292839808423a5062499f588f557000c5d15/visions/language-support-for-BufferView.md#non-escaping-bufferview) 
+
+## Motivation
+
+An efficient way to provide one piece of code with temporary access to data stored in some other piece of code is with a pointer to the data in memory.
+Swift's `Unsafe*Pointer` family of types can be used here, but as the name implies, using these types can be error-prone.
+
+For example, suppose `Array` had a property `unsafeBufferPointer` that returned an `UnsafeBufferPointer` to the contents of the array.
+Here's an attempt to use such a property:
+
+```
+let array = getArrayWithData()
+let buff = array.unsafeBufferPointer
+parse(buff) // <== 🛑 NOT SAFE!
+```
+
+One reason for this unsafety is because Swift's standard lifetime rules only apply to individual values.
+They cannot guarantee that `buff` will outlive the `array`, which means there is a risk that the compiler might choose to destroy `array` before the call to `parse`, which could result in `buff` referencing deallocated memory.
+(There are other reasons that this specific example is unsafe, but the lifetime issue is the one that specifically concerns us here.)
+
+Library authors trying to support this kind of code pattern today have a few options, but none are entirely satisfactory:
+
+* The client developer can manually insert `withExtendedLifetime` and similar annotations to control the lifetime of specific objects.
+ This is awkward and error-prone.
+We would prefer a mechanism where the library author can declare the necessary semantics and have the compiler automatically enforce them.
+* The library author can store a back-reference to the container as part of their "pointer" or "slice" object.
+However, this incurs reference counting overhead which sacrifices some of the performance gains that pointer-based designs are generally intended to provide.
+In addition, this approach is not possible in environments that lack support for dynamic allocation.
+* The library author can make the pointer information available only within a scoped function, but this is also unsafe, as demonstrated by well-meaning developers who extract the pointer out of such functions using code like that below.
+ Even when used correctly, scoped functions can lead to a pyramid of deeply-indented code blocks.
+
+```
+// 🛑 The following line of code is dangerous!  DO NOT DO THIS!
+let buff = array.withUnsafeBufferPointer { $0 }
+```
+
+## Proposed solution
+
+A "lifetime dependency" between two objects indicates that one of them can only be destroyed *after* the other.
+This dependency is enforced entirely at compile time; it requires no run-time support.
+These lifetime dependencies can be expressed in several different ways, with varying trade-offs of expressiveness and ease-of-use.
+
+### “Non-Escapable” Types
+
+In order to avoid changing the meaning of existing code, we will introduce a new type constraint spelled `~Escapable`.
+This type constraint can appear in a type declaration as a protocol.
+Consider a hypothetical `BufferReference` type that is similar to the standard library `UnsafeBufferPointer` or the `BufferView` type that is being proposed for inclusion in the standard library.
+It simply holds a pointer and size and can be used to access data stored in a contiguous block of memory.
+(We are not proposing this type; it is shown here merely for illustrative purposes.)
+
+```
+struct BufferReference<T>: ~Escapable {
+  private var base: UnsafePointer<T>
+  private var count: Int
+}
+```
+
+Because this type is marked `~Escapable`, any function that returns this type must specify a lifetime constraint on the return value, using one of the methods described in the following sections.
+In the most common cases, these constraints can be inferred automatically.
+However, to make the semantics clearer, we’ll begin by describing how one can explicitly specify a lifetime constraint in cases where the default inference rules do not apply.
+
+**Note**: A full proposal for `~Escapable` will be submitted elsewhere.
+The above is intended to cover just the minimal features of `~Escapable` required by this proposal.
+
+### Explicit Lifetime Dependency Annotations
+
+We propose new return value annotations to explicitly describe lifetime dependencies.
+For example, let’s consider adding support for our hypothetical `BufferReference` type to `Array`.
+Our proposal would allow you to declare an `array.bufferReference()` method as follows:
+
+```
+extension Array {
+  borrowing func bufferReference() -> borrow(self) BufferReference<Element> {
+     ... construct a BufferReference ...
+  }
+}
+```
+
+The annotation `borrow(self)` indicates that the returned value has "borrowed" the contents of the array (`self`).
+This is because the returned `BufferReference<Element>` has read-only access to the stored contents of the array.
+Note how this return type aligns with the `borrowing func` declaration that declares read-only borrowed access to the array for the lifetime of the function.
+In essence, the `borrow(self)` annotation extends that borrowed access beyond the function lifetime to include the lifetime of the returned value.
+Specifically, the `borrow(self)` annotation informs the compiler that:
+
+* The array must not be destroyed until after the `BufferReference<Element>` is destroyed.
+ This ensures that use-after-free cannot occur.
+* The array must not be mutated while the  `BufferReference<Element>` value exists.
+ This enforces the usual Swift exclusivity rules.
+
+In addition to `borrow(self)`, we also propose supporting three other lifetime dependency annotations:
+
+#### `mutate(self)`  or  `mutate(arg)`
+
+Let’s consider another hypothetical type: a `MutatingBufferReference<T>` type that could provide indirect mutating access to a block of memory.
+ This would need to be exposed slightly differently, since it provides *write* access:
+
+```
+func mutatingBufferReference(to: inout Array) -> mutate(to) MutatingBufferReference<Element> {
+     ... construct a MutatingBufferReference ...
+}
+```
+
+We’ve written this example as a free function rather than as a method to show how this annotation syntax can be used to express constraints that apply to a particular argument.
+The `mutate(to)` annotation indicates that the returned value has exclusive read/write access to the contents of the array, which is passed as the `inout` argument `to`.This means that no other read or write access to the argument will be allowed for as long as the returned value exists.
+
+#### `consume(self)  or  consume(arg)`
+
+In addition to allowing `BufferReference` values to be constructed directly from arrays, the author of our hypothetical type would also want to control the lifetimes of `BufferReference` values constructed from pre-existing `BufferReference` values.
+There are two different situations:
+
+We might want to create a new `BufferReference` while destroying a pre-existing one.
+For example, we may want a method that provides a new reference that excludes the initial items:
+
+```
+extension BufferReference {
+  consuming func drop(first: Int) -> consume(self) BufferReference<Element> { ... }
+}
+```
+
+This supports code like the following;
+
+```
+let a: Array<Int>
+let ref1 = a.bufferReference() // ref1 cannot outlive a
+let ref2 = ref1.drop(4) // ref2 also cannot outlive a
+```
+
+Note that in `ref1.drop(4)`, the lifetime of `ref2` does not depend on `ref1`.
+Rather, `ref2` has inherited `ref1`’s dependency on the lifetime of `a`.
+
+#### `copy(self)`  or  `copy(arg)`
+
+A similar concern arises even when the source is not being consumed.
+
+```
+extension BufferReference {
+  func dropping(first: Int) -> copy(self) BufferReference<Element> { ... }
+}
+```
+
+As with the `consume(self)` example above, the new `BufferReference` will inherit the lifetime of the original.
+
+The annotations can be combined in various ways to express complex lifetime interactions between the return value and the arguments:
+
+```
+func complexView(data: Array<Item>, statistics: Array<Statistics>, other: Int)
+     -> borrow(data) mutate(statistics) ComplexReferenceType
+{ ... }
+```
+
+#### Allowed Lifetime Dependencies
+
+Only certain types of lifetime dependencies make sense, depending on the type of argument.
+ The syntax is somewhat different for functions and methods, though the basic rules are essentially the same.
+
+**Functions:** A function with a lifetime dependency annotation generally takes this form:
+
+```
+func f(arg: <parameter-convention> ArgType) -> <lifetime-type>(arg) ResultType
+```
+
+Where
+
+*  *`parameter-convention`* is one of the ownership specifiers **`borrowing`**, **`consuming`**, or **`inout`**, (this may be implied by Swift’s default parameter ownership rules),
+* `*lifetime-type*` is one of the lifetime dependency annotations **`copy`**, **`borrow`**, **`consume`**, or **`mutate`**.
+* `ResultType` must be `~Escapable`.
+
+Further:
+
+* `borrow` lifetime-type is only permitted with a `borrowing` parameter-convention
+* `mutate` lifetime-type is only permitted with an `inout` parameter-convention
+* `consume` lifetime-type is only permitted with a `consuming` parameter-convention
+* `copy` lifetime-type is only permitted with `borrowing` or `inout` parameter-convention
+
+**Methods:** Similar rules apply to `self` lifetime dependencies on methods.
+ Given a method of this form:
+
+```
+   <mutation-modifier> func method(... args ...) -> <lifetime-type>(self) ResultType
+```
+
+We only permit
+
+* A `borrow(self)` lifetime dependency with a `borrowing` mutation-modifier
+* A `mutate(self)` lifetime dependency with a `mutating` mutation-modifier
+* A `consume(self)` lifetime dependency with a `consuming` mutation-modifier
+* A `copy(self)` lifetime dependency with a `borrowing` or `inout` mutation-modifier
+
+The rules above apply regardless of whether the parameter-convention or mutation-modifier is explicitly written or is implicit.
+
+**Initializers:** An initializer dependency annotation takes one of two forms.
+An initializer can define a lifetime dependency on one of its arguments.
+ In this case, the rules are the same as for “Functions” above:
+
+```
+init(arg: <parameter-convention> ArgType) -> <lifetime-type>(arg) Self
+```
+
+### Implicit Lifetime Dependencies
+
+The syntax above allows developers to explicitly annotate lifetime dependencies in their code.
+But because the possibilities are limited, we can usually allow the compiler to infer the dependency.
+The detailed rules are below, but generally we require that the return type be `~Escapable` and that there be one “obvious” source for the dependency.
+
+In particular, for methods, whenever there is an explicit mutation type, we can infer the matching lifetime dependency on `self`:
+
+```
+struct NonEscapableType: ~Escapable { ... }
+struct S {
+  borrowing func f(...) -> /* borrow(self) */ NonEscapableType
+  mutating func f(...) -> /* mutate(self) */ NonEscapableType
+  consuming func f(...) -> /* consume(self) */ NonEscapableType
+```
+
+For free or static functions or initializers, we can infer when there is one obvious argument to serve as the source of the dependency.
+Specifically, we’ll do this when there is one argument that is `~Escapable` or `~Copyable` (these are the types that already have lifetime restrictions, so are the natural types to expect for this role) and has an explicit parameter convention.
+For example:
+
+```
+struct Type1: ~Copyable /* Or: ~Escapable */ /* Or: ~Copyable & ~Escapable */
+struct Type2: ~Escapable { ... }
+func f(..., arg1: borrowing Type1, ...) -> /* borrow(arg1) */ Type2
+func f(..., arg1: consuming Type1, ...) -> /* consume(arg1) */ Type2
+func f(..., arg1: inout Type1, ...) -> /* mutate(arg1) */ Type2
+```
+
+We expect these implicit inferences to cover most cases, with the explicit form only occasionally being necessary in practice.
+
+## Detailed design
+
+### Grammar
+
+This new syntax adds an optional lifetime modifier just before the return type.
+This modifies *function-result* in the Swift grammar as follows:
+
+>
+> *function-signature* → *parameter-clause* **`async`***?* **`throws`***?* *function-result**?* \
+> *function-signature* → *parameter-clause* **`async`***?* **`rethrows`** *function-result**?* \
+> *function-result* → **`->`** *attributes**?* *lifetime-modifiers**?* *type*
+> *lifetime-modifiers* **`->`** *lifetime-modifier* *lifetime-modifiers**?*
+> *lifetime-modifier* **`->`** *lifetime-modifier-type* **`(`** **`self`** `**)**` \
+> *lifetime-modifier* **`->`** *lifetime-modifier-type* **`(`** *external-parameter-name* `**)**` \
+> *lifetime-modifier* **`->`** *lifetime-modifier-type* **`(`** *parameter-index* `**)**` 
+> *lifetime-modifier-type* **`->`** **`copy`** | **`borrow`** | **`mutate`** | **`consume`**
+>
+
+Here, the argument to the lifetime modifier must be one of the following:
+
+*  *external-parameter-name:* the external name of one of the function parameters,
+* *parameter-index:* a numeric index of one of the parameters in the *parameter-clause* (the first parameter is number zero), or
+* the token **`self`**.
+
+Additionally, the argument referred to by the *external-parameter-name* or *parameter-index* must have an explicit *parameter-modifier* of `inout`, `borrowing`, or `consuming`.
+If the *lifetime-modifier* is the token `**self**`**,** then the method must have a *mutation-modifier* of `mutating`, `borrowing`, or `consuming`.
+
+#### Initializers
+
+Initializers can have arguments, and there are cases where users will want to specify a lifetime dependency between one or more arguments and the constructed value.
+We propose allowing initializers to write out an explicit return clause for this case:
+
+```
+struct S {
+  init(arg1: Type1) -> borrow(arg1) Self
+}
+```
+
+This syntax will be rejected if the return type is not exactly the token `Self`.
+
+> Grammar of an initializer declaration:
+>
+> *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`throws`***?* *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body* \
+> *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`rethrows`** *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body*
+> *initializer-lifetime-modifier* → `**->**` *lifetime-modifiers* ** **`Self`**
+
+### Inference Rules
+
+If there is no explicit lifetime dependency, we will automatically infer one according to the following rules:
+
+**For methods where the return type is `~Escapable` and there is an explicit mutation type**, we will infer a dependency against self, depending on the mutation type of the function.
+Note that this is not affected by the presence, type, or modifier of any other arguments to the method.
+Specifically, we will infer:
+
+* a `borrow` lifetime dependency for a method that borrows `self`
+* a `mutate` lifetime dependency for a method that is `mutating` on self
+* a `consume` lifetime dependency for a method that is `consuming` on self
+
+**For a free or static functions or initializers with at least one argument,** we will infer a lifetime dependency when all of the following are true:
+
+* the return type is `~Escapable`,
+* there is exactly one argument that is either `~Copyable` or `~Escapable`
+* that argument has an explicit `borrowing`, `consuming`, or `inout` convention specified
+
+In this case, the compiler will infer:
+
+* a `borrow` lifetime dependency for a function whose only `~Escapable` or `~Copyable` argument is `borrowing` 
+* a `mutate` lifetime dependency for a function whose only `~Escapable` or `~Copyable` argument is `inout`
+* a `consume` lifetime dependency for a function whose only `~Escapable` or `~Copyable` argument is `consuming`
+
+**In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
+If a function, method, or initializer has a `~Escapable` return type, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
+
+### Semantics
+
+The syntax above declares a lifetime dependency between the return value of a function or method and a function argument, method argument, or `self`.
+
+If the `lifetime-modifier` (either specified or inferred) is `borrow` or `mutate`, then we can refer to the argument or `self` as the *source* of the dependency, and the return value then has respectively a *borrow* *lifetime dependency* or a *mutate lifetime dependency* ** on the source.
+When this occurs, the compiler may shorten the lifetime of the return value or extend the lifetime of the source value within the existing language rules in order to meet the requirement.
+Further, the compiler will issue diagnostics in the following cases:
+
+* If the return value cannot be destroyed before the source value.
+This can happen if there are other factors (such as nested scopes, function returns, or closure captures) that contradict the lifetime dependency.
+* For a borrow lifetime dependency, if the source value is mutated before the return value is destroyed.
+* For a mutate lifetime dependency, if the source value is accessed or mutated before the return value is destroyed.
+
+If the `lifetime-modifier` is `consume` or `copy`, then the return value from the function or method gains the same lifetime dependency as the function argument, method argument, or `self`.
+In this case, we’ll refer to the argument or `self` as the *original* value.
+In this case, the original value must itself must be `~Escapable`, and must in turn have a borrow or mutate lifetime dependency on some other source value.
+The return value will then have a borrow or mutate lifetime dependency on that same source value that will be enforced by the compiler as above.
+
+### Relation to ~Escapable
+
+The lifetime dependencies described in this document can be applied only to `~Escapable` return values.
+Further, any return value that is `~Escapable` must have a lifetime dependency.
+In particular, this implies that the initializer for a non-escapable type must have at least one argument.
+
+```
+struct S: ~Escapable {
+  init() {} // 🛑 Error: ~Escapable return type must have lifetime dependency
+}
+```
+
+## Source compatibility
+
+Everything discussed here is additive to the existing Swift grammar and type system.
+It has no effect on existing code.
+
+The tokens `-> borrowing` in a function declaration might indicate the beginning of a borrowing lifetime annotation or could indicate that the function returns an existing type called `borrowing`.
+This ambiguity can be fully resolved in the parser by looking for an open parenthesis `(` after the `borrowing`, `mutating`, `copy`, or `consume` token.
+
+## Effect on ABI stability
+
+Lifetime dependency annotations may affect how values are passed into functions, and thus adding or removing one of these annotations should generally be expected to affect the ABI.
+
+## Effect on API resilience
+
+Adding a lifetime dependency constraint can cause existing valid source code to no longer be correct, since it introduces new restrictions on the lifetime of values that pre-existing code may not satisfy.
+Removing a lifetime dependency constraint only affects existing source code in that it may change when deinitializers run, altering the ordering of deinitializer side-effects.
+
+## Alternatives considered
+
+### Different Position
+
+We propose above putting the annotation on the return value, which we believe matches the intuition that the method or property is producing this lifetime dependence alongside the returned value.
+It would also be possible to put an annotation on the parameters instead:
+
+```
+func f(@resultDependsOn arg1: Array<Int>) -> BufferReference<Int>
+```
+
+Depending on the exact language in use, it could also be more natural to put the annotation after the return value.
+However, we worry that this hides this critical information in cases where the return type is longer or more complex.
+
+```
+func f(arg1: Array<Int>) -> BufferReference<Int> dependsOn(arg1)
+```
+
+### Different spellings
+
+We propose above using the existing `borrow`/`mutate`/`consume`/`copy` keywords, since we feel the new behaviors have a substantial similarity to how similar keywords are used elsewhere in the language.
+
+Other alternatives considered include:
+
+```
+func f(arg1: Array<Int>) -> @dependsOn(arg1) BufferReference<Int>
+```
+
+The above syntax states the dependency, but could require elaboration to clarify the type of dependency.
+As illustrated by the inference rules above, there is often only one reasonable lifetime dependency type for a particular situation.
+But `copy` and “Downgraded dependencies” described below complicate this somewhat.
+
+```
+func f(arg1: Array<Int>) -> @scoped(arg1) BufferReference<Int>
+```
+
+Lifetime dependencies are sometimes referred to as “scoped access.” We find this terminology less natural in practice.
+
+#### Implicit argument convention or method mutation modifier
+
+The Detailed design above requires that any function, method, or property that returns a `~Escapable` type must have an implicit or explicit lifetime constraint.
+Further, it requires that any lifetime constraint refer to an argument with an *explicit* mutation convention or `self` where the method has an *explicit* mutation modifier.
+For example:
+
+```
+func f(arg1: Type1) -> borrow(arg1) NonEscapableType // 🛑 `arg1` must be marked `borrowing`
+
+... Type ... {
+   func f() -> borrow(self) Self // 🛑 method must be marked `borrowing`
+}
+```
+
+Requiring an explicit mutation specification seems to us to improve readability, but could potentially be dropped by relying on Swift’s usual default argument and method conventions.
+
+## Future Directions
+
+#### **Lifetime Dependencies for Computed Properties**
+
+It might be useful to allow lifetime dependencies between `self` and the value returned by a computed property.
+There is some ambiguity here, since resilience hides the distinction between a computed and stored property, and it’s not clear that there is any use for lifetime dependencies when returning stored properties.
+In particular, the resilience concern might prevent us from inferring lifetime dependencies for properties across module boundaries.
+The notation for an explicit lifetime dependency on a property might look like the following:
+
+```
+struct Container {
+  var view: ReturnType { borrowing get }
+}
+
+extension Type1 {
+  var transformedView: Type1 { consuming get }
+}
+```
+
+Where `borrowing` or `consuming` would indicate that the returned value has a lifetime dependency on `self`.
+We expect that the lifetime notation would be mandatory for any property that provided a `~Escaping` value.
+
+#### Lifetime Dependencies for Escapable Types
+
+This proposal has deliberately limited the application of lifetime dependencies to return types that are `~Escapable`.
+This simplifies the model by identifying `~Escapable` types as exactly those types that can carry such dependencies.
+It also helps simplify the enforcement of lifetime constraints by guaranteeing that constrained values cannot escape before being returned.
+We expect that in the future, additional investigation can reveal a way to relax this restriction.
+
+### Downgraded Dependencies
+
+```
+// This is forbidden by the current proposal, but could be supported in theory
+func f(arg1: inout Array<Int>) -> borrow BufferReference<Int>
+```
+
+Our current proposal requires that `inout` arguments only be used with `mutate` lifetime dependencies (or `copy` if the argument is itself `~Escapable`).
+It may be useful to permit “downgrading” the access so that the function can have mutating access to the argument while it is running, but only extends read-only `borrow` access to the return value.
+We are not confident that we can make this fully safe today:  With our current diagnostic work, we cannot prevent the implementor of `f` from “sneaking” read-write access into the returned value.
+We hope to expand these diagnostics in the future, at which point we may be able to safely lift this restriction.
+
+

From 243e33b516c993bdbb7adaef51c940278c329f4b Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Wed, 24 Jan 2024 18:23:42 -0800
Subject: [PATCH 02/59] Whitespace cleanup

---
 proposals/NNNN-lifetime-dependency.md | 35 +++++++++++++--------------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 3e4c6e2b1e..3f177fa2a7 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -40,13 +40,13 @@ They cannot guarantee that `buff` will outlive the `array`, which means there is
 Library authors trying to support this kind of code pattern today have a few options, but none are entirely satisfactory:
 
 * The client developer can manually insert `withExtendedLifetime` and similar annotations to control the lifetime of specific objects.
- This is awkward and error-prone.
-We would prefer a mechanism where the library author can declare the necessary semantics and have the compiler automatically enforce them.
+  This is awkward and error-prone.
+  We would prefer a mechanism where the library author can declare the necessary semantics and have the compiler automatically enforce them.
 * The library author can store a back-reference to the container as part of their "pointer" or "slice" object.
-However, this incurs reference counting overhead which sacrifices some of the performance gains that pointer-based designs are generally intended to provide.
-In addition, this approach is not possible in environments that lack support for dynamic allocation.
+  However, this incurs reference counting overhead which sacrifices some of the performance gains that pointer-based designs are generally intended to provide.
+  In addition, this approach is not possible in environments that lack support for dynamic allocation.
 * The library author can make the pointer information available only within a scoped function, but this is also unsafe, as demonstrated by well-meaning developers who extract the pointer out of such functions using code like that below.
- Even when used correctly, scoped functions can lead to a pyramid of deeply-indented code blocks.
+  Even when used correctly, scoped functions can lead to a pyramid of deeply-indented code blocks.
 
 ```
 // 🛑 The following line of code is dangerous!  DO NOT DO THIS!
@@ -90,7 +90,7 @@ Our proposal would allow you to declare an `array.bufferReference()` method as f
 ```
 extension Array {
   borrowing func bufferReference() -> borrow(self) BufferReference<Element> {
-     ... construct a BufferReference ...
+    ... construct a BufferReference ...
   }
 }
 ```
@@ -102,20 +102,20 @@ In essence, the `borrow(self)` annotation extends that borrowed access beyond th
 Specifically, the `borrow(self)` annotation informs the compiler that:
 
 * The array must not be destroyed until after the `BufferReference<Element>` is destroyed.
- This ensures that use-after-free cannot occur.
+  This ensures that use-after-free cannot occur.
 * The array must not be mutated while the  `BufferReference<Element>` value exists.
- This enforces the usual Swift exclusivity rules.
+  This enforces the usual Swift exclusivity rules.
 
 In addition to `borrow(self)`, we also propose supporting three other lifetime dependency annotations:
 
 #### `mutate(self)`  or  `mutate(arg)`
 
 Let’s consider another hypothetical type: a `MutatingBufferReference<T>` type that could provide indirect mutating access to a block of memory.
- This would need to be exposed slightly differently, since it provides *write* access:
+This would need to be exposed slightly differently, since it provides *write* access:
 
 ```
 func mutatingBufferReference(to: inout Array) -> mutate(to) MutatingBufferReference<Element> {
-     ... construct a MutatingBufferReference ...
+  ... construct a MutatingBufferReference ...
 }
 ```
 
@@ -170,7 +170,7 @@ func complexView(data: Array<Item>, statistics: Array<Statistics>, other: Int)
 #### Allowed Lifetime Dependencies
 
 Only certain types of lifetime dependencies make sense, depending on the type of argument.
- The syntax is somewhat different for functions and methods, though the basic rules are essentially the same.
+The syntax is somewhat different for functions and methods, though the basic rules are essentially the same.
 
 **Functions:** A function with a lifetime dependency annotation generally takes this form:
 
@@ -192,10 +192,10 @@ Further:
 * `copy` lifetime-type is only permitted with `borrowing` or `inout` parameter-convention
 
 **Methods:** Similar rules apply to `self` lifetime dependencies on methods.
- Given a method of this form:
+Given a method of this form:
 
 ```
-   <mutation-modifier> func method(... args ...) -> <lifetime-type>(self) ResultType
+<mutation-modifier> func method(... args ...) -> <lifetime-type>(self) ResultType
 ```
 
 We only permit
@@ -207,9 +207,8 @@ We only permit
 
 The rules above apply regardless of whether the parameter-convention or mutation-modifier is explicitly written or is implicit.
 
-**Initializers:** An initializer dependency annotation takes one of two forms.
-An initializer can define a lifetime dependency on one of its arguments.
- In this case, the rules are the same as for “Functions” above:
+**Initializers:** An initializer can define a lifetime dependency on one of its arguments.
+In this case, the rules are the same as for “Functions” above:
 
 ```
 init(arg: <parameter-convention> ArgType) -> <lifetime-type>(arg) Self
@@ -265,7 +264,7 @@ This modifies *function-result* in the Swift grammar as follows:
 
 Here, the argument to the lifetime modifier must be one of the following:
 
-*  *external-parameter-name:* the external name of one of the function parameters,
+* *external-parameter-name:* the external name of one of the function parameters,
 * *parameter-index:* a numeric index of one of the parameters in the *parameter-clause* (the first parameter is number zero), or
 * the token **`self`**.
 
@@ -413,7 +412,7 @@ For example:
 func f(arg1: Type1) -> borrow(arg1) NonEscapableType // 🛑 `arg1` must be marked `borrowing`
 
 ... Type ... {
-   func f() -> borrow(self) Self // 🛑 method must be marked `borrowing`
+  func f() -> borrow(self) Self // 🛑 method must be marked `borrowing`
 }
 ```
 

From b30308d279557fcb0315e1e1d50ad0003ba10220 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Wed, 24 Jan 2024 18:25:31 -0800
Subject: [PATCH 03/59] Fix formatting

---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 3f177fa2a7..5d4ddb375d 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -181,7 +181,7 @@ func f(arg: <parameter-convention> ArgType) -> <lifetime-type>(arg) ResultType
 Where
 
 *  *`parameter-convention`* is one of the ownership specifiers **`borrowing`**, **`consuming`**, or **`inout`**, (this may be implied by Swift’s default parameter ownership rules),
-* `*lifetime-type*` is one of the lifetime dependency annotations **`copy`**, **`borrow`**, **`consume`**, or **`mutate`**.
+* *`lifetime-type`* is one of the lifetime dependency annotations **`copy`**, **`borrow`**, **`consume`**, or **`mutate`**.
 * `ResultType` must be `~Escapable`.
 
 Further:

From ccc54d9217ad29405265b8c4186c18475d129129 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Fri, 26 Jan 2024 09:28:57 -0800
Subject: [PATCH 04/59] Future direction: Lifetime dependencies between
 arguments

---
 proposals/NNNN-lifetime-dependency.md | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 5d4ddb375d..95a15b80b4 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -420,7 +420,7 @@ Requiring an explicit mutation specification seems to us to improve readability,
 
 ## Future Directions
 
-#### **Lifetime Dependencies for Computed Properties**
+#### Lifetime Dependencies for Computed Properties
 
 It might be useful to allow lifetime dependencies between `self` and the value returned by a computed property.
 There is some ambiguity here, since resilience hides the distinction between a computed and stored property, and it’s not clear that there is any use for lifetime dependencies when returning stored properties.
@@ -447,7 +447,7 @@ This simplifies the model by identifying `~Escapable` types as exactly those typ
 It also helps simplify the enforcement of lifetime constraints by guaranteeing that constrained values cannot escape before being returned.
 We expect that in the future, additional investigation can reveal a way to relax this restriction.
 
-### Downgraded Dependencies
+#### Downgraded Dependencies
 
 ```
 // This is forbidden by the current proposal, but could be supported in theory
@@ -459,4 +459,11 @@ It may be useful to permit “downgrading” the access so that the function can
 We are not confident that we can make this fully safe today:  With our current diagnostic work, we cannot prevent the implementor of `f` from “sneaking” read-write access into the returned value.
 We hope to expand these diagnostics in the future, at which point we may be able to safely lift this restriction.
 
+#### Lifetime Dependencies between arguments
 
+A caller may need assurance that a callee will honor a lifetime dependency between two arguments.
+For example, if a function is going to destroy a container and a reference to that container in the process of computing some result,
+it needs to guarantee that the reference is destroyed before the container:
+```
+func f(container: consuming ContainerType, ref: borrow(container) consuming RefType) -> ResultType
+```

From 2992389fa8b1465930182111f0cc080664cff8c0 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Tue, 6 Feb 2024 10:08:39 -0800
Subject: [PATCH 05/59] Link to pitch thread

---
 proposals/NNNN-lifetime-dependency.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 95a15b80b4..45cb68fe9a 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -4,6 +4,7 @@
 * Authors: [Andrew Trick](https://github.com/atrick), [Meghana Gupta](https://github.com/meg-gupta), [Tim Kientzle](https://github.com/tbkka)
 * Review Manager: TBD
 * Status: **Awaiting implementation**
+* Review: ([pitch](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865))
 
 ## Introduction
 

From ba3946cd04dba205e756d99fcfa396ae00994dc6 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Wed, 7 Feb 2024 15:41:29 -0800
Subject: [PATCH 06/59] New examples for Future Directions

---
 proposals/NNNN-lifetime-dependency.md | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 45cb68fe9a..3724089c88 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -446,6 +446,7 @@ We expect that the lifetime notation would be mandatory for any property that pr
 This proposal has deliberately limited the application of lifetime dependencies to return types that are `~Escapable`.
 This simplifies the model by identifying `~Escapable` types as exactly those types that can carry such dependencies.
 It also helps simplify the enforcement of lifetime constraints by guaranteeing that constrained values cannot escape before being returned.
+Most importantly, this restriction helps ensure that the new semantics (especially lifetime dependency inference) cannot accidentally break existing code.
 We expect that in the future, additional investigation can reveal a way to relax this restriction.
 
 #### Downgraded Dependencies
@@ -468,3 +469,25 @@ it needs to guarantee that the reference is destroyed before the container:
 ```
 func f(container: consuming ContainerType, ref: borrow(container) consuming RefType) -> ResultType
 ```
+
+#### Lifetime Dependencies for Tuples
+
+It should be possible to return a tuple where one part has a lifetime dependency.
+For example:
+```swift
+func f(a: consume A, b: B) -> (consume(a) C, B)
+```
+We expect to address this in the near future in a separate proposal.
+
+#### Lifetime Dependencies for containers and their elements
+
+It should be possible to return containers with collections of lifetime-constrained elements.
+For example, a container may want to return a partition of its contents:
+```swift
+borrowing func chunks(n: Int) -> borrow(self) SomeList<borrow(self) BufferView<UInt8>>
+```
+We're actively looking into ways to support these more involved cases and expect to address this in a future proposal.
+
+## Acknowledgements
+
+Dima Galimzianov provided several examples for Future Directions.

From 0aab19d2f83319ceda5934d79f5c46e63e137ad8 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Wed, 7 Feb 2024 15:48:29 -0800
Subject: [PATCH 07/59] Match the implementation:  Use local parameter names
 for argument references

---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 3724089c88..a827d5cd2d 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -265,7 +265,7 @@ This modifies *function-result* in the Swift grammar as follows:
 
 Here, the argument to the lifetime modifier must be one of the following:
 
-* *external-parameter-name:* the external name of one of the function parameters,
+* *local-parameter-name:* the local name of one of the function parameters,
 * *parameter-index:* a numeric index of one of the parameters in the *parameter-clause* (the first parameter is number zero), or
 * the token **`self`**.
 

From f9b06b7bf784cd7925117da81217e19d6189e1d8 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Wed, 7 Feb 2024 17:44:25 -0800
Subject: [PATCH 08/59] Clarify some Alternatives and Future Directions

---
 proposals/NNNN-lifetime-dependency.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index a827d5cd2d..f995d79d60 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -387,6 +387,8 @@ func f(arg1: Array<Int>) -> BufferReference<Int> dependsOn(arg1)
 
 We propose above using the existing `borrow`/`mutate`/`consume`/`copy` keywords, since we feel the new behaviors have a substantial similarity to how similar keywords are used elsewhere in the language.
 
+We also considered `borrowing`/`mutating`/`consuming`/`copying` but felt that the semantic differences merited using a different form of these words.
+
 Other alternatives considered include:
 
 ```
@@ -424,7 +426,7 @@ Requiring an explicit mutation specification seems to us to improve readability,
 #### Lifetime Dependencies for Computed Properties
 
 It might be useful to allow lifetime dependencies between `self` and the value returned by a computed property.
-There is some ambiguity here, since resilience hides the distinction between a computed and stored property, and it’s not clear that there is any use for lifetime dependencies when returning stored properties.
+There is some ambiguity here, since resilience hides the distinction between a computed and stored property.
 In particular, the resilience concern might prevent us from inferring lifetime dependencies for properties across module boundaries.
 The notation for an explicit lifetime dependency on a property might look like the following:
 

From 84521ca14416048bdf30d5119e609ca8355c1e1a Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Mon, 12 Feb 2024 10:09:31 -0800
Subject: [PATCH 09/59] methods are `mutating`, not `inout`

---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index f995d79d60..adacb32465 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -204,7 +204,7 @@ We only permit
 * A `borrow(self)` lifetime dependency with a `borrowing` mutation-modifier
 * A `mutate(self)` lifetime dependency with a `mutating` mutation-modifier
 * A `consume(self)` lifetime dependency with a `consuming` mutation-modifier
-* A `copy(self)` lifetime dependency with a `borrowing` or `inout` mutation-modifier
+* A `copy(self)` lifetime dependency with a `borrowing` or `mutating` mutation-modifier
 
 The rules above apply regardless of whether the parameter-convention or mutation-modifier is explicitly written or is implicit.
 

From 3055becc53a3c3c2551dfceb8de04316902e4c5d Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Wed, 21 Feb 2024 17:15:57 -0800
Subject: [PATCH 10/59] Expand alternative syntaxes

---
 proposals/NNNN-lifetime-dependency.md | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index adacb32465..a7ed87ef39 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -389,21 +389,19 @@ We propose above using the existing `borrow`/`mutate`/`consume`/`copy` keywords,
 
 We also considered `borrowing`/`mutating`/`consuming`/`copying` but felt that the semantic differences merited using a different form of these words.
 
-Other alternatives considered include:
-
-```
-func f(arg1: Array<Int>) -> @dependsOn(arg1) BufferReference<Int>
-```
-
-The above syntax states the dependency, but could require elaboration to clarify the type of dependency.
-As illustrated by the inference rules above, there is often only one reasonable lifetime dependency type for a particular situation.
-But `copy` and “Downgraded dependencies” described below complicate this somewhat.
-
+We could have a single `scoped` annotation that covers the `borrow` and `mutate` semantics described above,
+since the semantics are implied by the argument.
+Similarly we could collapse `copy` and `consume` to use just `copy` (since they are formally identical).
+That would give us two notations rather than the four in our current proposal:
 ```
-func f(arg1: Array<Int>) -> @scoped(arg1) BufferReference<Int>
+// `borrow` and `mutate` semantics could share a single annotation:
+func f(arg1: borrow Array<Int>) -> scoped(arg1) BufferReference<Int> // Same as `borrow(arg1)`
+func f(arg1: inout Array<Int>) -> scoped(arg1) BufferReference<Int> // Same as `mutate(arg1)`
 ```
 
-Lifetime dependencies are sometimes referred to as “scoped access.” We find this terminology less natural in practice.
+This single `scoped` notation would prevent us from eventually supporting the
+“Downgraded dependencies” described below.
+The `scoped` notation could also be spelled `@scoped` or `@dependsOn`.
 
 #### Implicit argument convention or method mutation modifier
 

From 78d07f27286a03d44976122732b44e4a39496a22 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Thu, 21 Mar 2024 08:48:34 -0700
Subject: [PATCH 11/59] Overhaul to adopt the new `@dependsOn()` syntax

---
 proposals/NNNN-lifetime-dependency.md | 384 +++++++++++++-------------
 1 file changed, 186 insertions(+), 198 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index a7ed87ef39..b8e3213c2e 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -8,15 +8,16 @@
 
 ## Introduction
 
-We would like to propose extensions to Swift's function-declaration syntax that allow authors to specify lifetime dependencies between the return value and one or more of the arguments.
+We would like to propose extensions to Swift's function-declaration syntax that allow authors to specify lifetime dependencies between the return value and one or more of the parameters.
 These would also be useable with methods that wish to declare a dependency on `self`.
 To reduce the burden of manually adding such annotations, we also propose inferring lifetime dependencies in certain common cases without requiring any additional annotations.
 
-This is a key requirement for the `BufferView` type being discussed elsewhere, and is closely related to the proposal for `~Escapable` types.
+This is a key requirement for the `StorageView` type (previously called `BufferView`) being discussed elsewhere, and is closely related to the proposal for `~Escapable` types.
 
 #### See Also
 
 * **TODO**: **** Forum thread discussing this proposal
+* [Pitch Thread for StorageView](https://forums.swift.org/t/pitch-safe-access-to-contiguous-storage/69888)
 * [Forum discussion of BufferView language requirements](https://forums.swift.org/t/roadmap-language-support-for-bufferview)
 * [Proposed Vision document for BufferView language requirements (includes description of ~Escapable)](https://github.com/atrick/swift-evolution/blob/fd63292839808423a5062499f588f557000c5d15/visions/language-support-for-BufferView.md#non-escaping-bufferview) 
 
@@ -28,7 +29,7 @@ Swift's `Unsafe*Pointer` family of types can be used here, but as the name impli
 For example, suppose `Array` had a property `unsafeBufferPointer` that returned an `UnsafeBufferPointer` to the contents of the array.
 Here's an attempt to use such a property:
 
-```
+```swift
 let array = getArrayWithData()
 let buff = array.unsafeBufferPointer
 parse(buff) // <== 🛑 NOT SAFE!
@@ -49,7 +50,7 @@ Library authors trying to support this kind of code pattern today have a few opt
 * The library author can make the pointer information available only within a scoped function, but this is also unsafe, as demonstrated by well-meaning developers who extract the pointer out of such functions using code like that below.
   Even when used correctly, scoped functions can lead to a pyramid of deeply-indented code blocks.
 
-```
+```swift
 // 🛑 The following line of code is dangerous!  DO NOT DO THIS!
 let buff = array.withUnsafeBufferPointer { $0 }
 ```
@@ -60,187 +61,214 @@ A "lifetime dependency" between two objects indicates that one of them can only
 This dependency is enforced entirely at compile time; it requires no run-time support.
 These lifetime dependencies can be expressed in several different ways, with varying trade-offs of expressiveness and ease-of-use.
 
-### “Non-Escapable” Types
+### Background: "Escapable" and “Nonescapable” Types
 
-In order to avoid changing the meaning of existing code, we will introduce a new type constraint spelled `~Escapable`.
-This type constraint can appear in a type declaration as a protocol.
-Consider a hypothetical `BufferReference` type that is similar to the standard library `UnsafeBufferPointer` or the `BufferView` type that is being proposed for inclusion in the standard library.
+In order to avoid changing the meaning of existing code, we will introduce two complementary type constraints:
+`Escapable` and `~Escapable`.
+These constraints can appear in a type declaration as a protocol.
+
+Normal Swift types are `Escapable` by default.
+This implies that they can be returned, stored in properties, or otherwise "escape" the local context.
+Conversely, types explicitly declared `~Escapable` are not allowed to escape the local context except in very specific circumstances.
+A separate proposal explains the general syntax and semantics of `Escapable` and `~Escapable` types.
+
+By themselves, `~Escapable` types have severe constraints on usage.
+For example, consider a hypothetical `BufferReference` type that is similar to the standard library `UnsafeBufferPointer` or the `StorageView` type that is being proposed for inclusion in the standard library.
 It simply holds a pointer and size and can be used to access data stored in a contiguous block of memory.
 (We are not proposing this type; it is shown here merely for illustrative purposes.)
 
-```
+```swift
 struct BufferReference<T>: ~Escapable {
   private var base: UnsafePointer<T>
   private var count: Int
 }
 ```
 
-Because this type is marked `~Escapable`, any function that returns this type must specify a lifetime constraint on the return value, using one of the methods described in the following sections.
+Because this type is marked `~Escapable`, it cannot be returned from a function or even initialized without some way to relax the escapability restrictions.
+This proposal provides a set of constraints that can tie the lifetime of a `~Escapable` value to the lifetime of some other value.
 In the most common cases, these constraints can be inferred automatically.
-However, to make the semantics clearer, we’ll begin by describing how one can explicitly specify a lifetime constraint in cases where the default inference rules do not apply.
-
-**Note**: A full proposal for `~Escapable` will be submitted elsewhere.
-The above is intended to cover just the minimal features of `~Escapable` required by this proposal.
 
 ### Explicit Lifetime Dependency Annotations
 
-We propose new return value annotations to explicitly describe lifetime dependencies.
-For example, let’s consider adding support for our hypothetical `BufferReference` type to `Array`.
+To make the semantics clearer, we’ll begin by describing how one can explicitly specify a lifetime constraint in cases where the default inference rules do not apply.
+
+Let’s consider adding support for our hypothetical `BufferReference` type to `Array`.
 Our proposal would allow you to declare an `array.bufferReference()` method as follows:
 
-```
+```swift
 extension Array {
-  borrowing func bufferReference() -> borrow(self) BufferReference<Element> {
+  borrowing func bufferReference() -> @dependsOn(self) BufferReference<Element> {
     ... construct a BufferReference ...
   }
 }
 ```
 
-The annotation `borrow(self)` indicates that the returned value has "borrowed" the contents of the array (`self`).
-This is because the returned `BufferReference<Element>` has read-only access to the stored contents of the array.
-Note how this return type aligns with the `borrowing func` declaration that declares read-only borrowed access to the array for the lifetime of the function.
-In essence, the `borrow(self)` annotation extends that borrowed access beyond the function lifetime to include the lifetime of the returned value.
-Specifically, the `borrow(self)` annotation informs the compiler that:
+The annotation `@dependsOn(self)` here indicates that the returned value must not outlive the array that produced it.
+Conceptually, it is a continuation of the function's borrowing access:
+the array is being borrowed by the function while the function executes and then continues to be borrowed by the `BufferReference` for as long as the return value exists.
+Specifically, the `@dependsOn(self)` annotation in this example informs the compiler that:
 
 * The array must not be destroyed until after the `BufferReference<Element>` is destroyed.
   This ensures that use-after-free cannot occur.
 * The array must not be mutated while the  `BufferReference<Element>` value exists.
-  This enforces the usual Swift exclusivity rules.
-
-In addition to `borrow(self)`, we also propose supporting three other lifetime dependency annotations:
+  This follows the usual Swift exclusivity rules for a borrowing access.
 
-#### `mutate(self)`  or  `mutate(arg)`
+#### Scoped Lifetime Dependency
 
 Let’s consider another hypothetical type: a `MutatingBufferReference<T>` type that could provide indirect mutating access to a block of memory.
-This would need to be exposed slightly differently, since it provides *write* access:
+Here's one way such a value might be produced:
 
-```
-func mutatingBufferReference(to: inout Array) -> mutate(to) MutatingBufferReference<Element> {
+```swift
+func mutatingBufferReference(to: inout Array, count: Int) -> @dependsOn(to) MutatingBufferReference<Element> {
   ... construct a MutatingBufferReference ...
 }
 ```
 
 We’ve written this example as a free function rather than as a method to show how this annotation syntax can be used to express constraints that apply to a particular argument.
-The `mutate(to)` annotation indicates that the returned value has exclusive read/write access to the contents of the array, which is passed as the `inout` argument `to`.This means that no other read or write access to the argument will be allowed for as long as the returned value exists.
+The `@dependsOn(to)` annotation indicates that the returned value depends on the argument named `to`.
+Because `count` is not mentioned in the lifetime dependency, that argument does not participate.
+Similar to the previous example:
 
-#### `consume(self)  or  consume(arg)`
+* The array will not be destroyed until after the `MutatingBufferReference<Element>` is destroyed.
+* No other read or write access to the array will be allowed for as long as the returned value exists.
 
-In addition to allowing `BufferReference` values to be constructed directly from arrays, the author of our hypothetical type would also want to control the lifetimes of `BufferReference` values constructed from pre-existing `BufferReference` values.
-There are two different situations:
+In both this and the previous case, the lifetime of the return value is "scoped" to the lifetime of the original value.
+Because lifetime dependencies can only be attached to `~Escapable` values, types that contain pointers will generally need to be `~Escapable` in order to provide safe semantics.
+As a result, **scoped lifetime dependencies** are the common case whenever an `Escapable` value (such as an Array or similar container) is providing a `~Escapable` value (such as the `BufferReference` or `MutatingBufferReference` in these examples).
 
-We might want to create a new `BufferReference` while destroying a pre-existing one.
-For example, we may want a method that provides a new reference that excludes the initial items:
+#### Copy Lifetime Dependency
 
-```
-extension BufferReference {
-  consuming func drop(first: Int) -> consume(self) BufferReference<Element> { ... }
+The case where a `~Escapable` value is used to produce a different `~Escapable` value is somewhat different.
+Here's a typical example that constructs a new `BufferReference` from an existing one:
+```swift
+struct BufferReference<T>: ~Escapable {
+  ...
+  consuming func drop(_: Int) -> @dependsOn(self) BufferReference<T> { ... }
+  ...
 }
 ```
 
-This supports code like the following;
+In this examples, the `~Escapable` result depends on a `~Escapable` value.
+Recall that `~Escapable` values such as these represent values that are already lifetime-constrained to another value.
 
-```
+For a `consuming` method, the return value cannot have a scoped lifetime dependency on the original value, since the original value no longer exists when the method returns.
+Instead, the return value must "copy" the lifetime dependency from the original:
+If the original `BufferReference` was borrowing some array, the new `BufferReference` will continue to borrow the same array.
+
+This supports coding patterns such as this:
+```swift
 let a: Array<Int>
 let ref1 = a.bufferReference() // ref1 cannot outlive a
 let ref2 = ref1.drop(4) // ref2 also cannot outlive a
 ```
 
-Note that in `ref1.drop(4)`, the lifetime of `ref2` does not depend on `ref1`.
-Rather, `ref2` has inherited `ref1`’s dependency on the lifetime of `a`.
-
-#### `copy(self)`  or  `copy(arg)`
-
-A similar concern arises even when the source is not being consumed.
-
-```
-extension BufferReference {
-  func dropping(first: Int) -> copy(self) BufferReference<Element> { ... }
-}
-```
-
-As with the `consume(self)` example above, the new `BufferReference` will inherit the lifetime of the original.
-
-The annotations can be combined in various ways to express complex lifetime interactions between the return value and the arguments:
-
-```
-func complexView(data: Array<Item>, statistics: Array<Statistics>, other: Int)
-     -> borrow(data) mutate(statistics) ComplexReferenceType
-{ ... }
-```
+After `ref1.drop(4)`, the lifetime of `ref2` does not depend on `ref1`.
+Rather, `ref2` has **inherited** or **copied** `ref1`’s dependency on the lifetime of `a`.
 
 #### Allowed Lifetime Dependencies
 
-Only certain types of lifetime dependencies make sense, depending on the type of argument.
+The previous sections described **scoped lifetime dependencies** and **copied lifetime dependencies**
+and showed how each type occurs naturally in different use cases.
+
+Now let's look at the full range of possibilities for explicit constraints.
 The syntax is somewhat different for functions and methods, though the basic rules are essentially the same.
 
-**Functions:** A function with a lifetime dependency annotation generally takes this form:
+**Functions:** A simple function with an explicit lifetime dependency annotation generally takes this form:
 
-```
-func f(arg: <parameter-convention> ArgType) -> <lifetime-type>(arg) ResultType
+```swift
+func f(arg: <parameter-convention> ArgType) -> @dependsOn(arg) ResultType
 ```
 
 Where
 
 *  *`parameter-convention`* is one of the ownership specifiers **`borrowing`**, **`consuming`**, or **`inout`**, (this may be implied by Swift’s default parameter ownership rules),
-* *`lifetime-type`* is one of the lifetime dependency annotations **`copy`**, **`borrow`**, **`consume`**, or **`mutate`**.
 * `ResultType` must be `~Escapable`.
 
-Further:
-
-* `borrow` lifetime-type is only permitted with a `borrowing` parameter-convention
-* `mutate` lifetime-type is only permitted with an `inout` parameter-convention
-* `consume` lifetime-type is only permitted with a `consuming` parameter-convention
-* `copy` lifetime-type is only permitted with `borrowing` or `inout` parameter-convention
+If the `ArgType` is `Escapable`, the return value will have a new scoped dependency on the argument.
+(This is the only possibility, as an `Escapable` value cannot have an existing lifetime dependency,
+so we cannot copy it.)
+A scoped dependency ensures the argument will not be destroyed while the result is alive.
+Also, access to the argument will be restricted for the lifetime of the result following Swift's usual exclusivity rules:
+
+* A `borrowing` parameter-convention extends borrowing access, prohibiting mutations of the argument.
+* An `inout` parameter-convention extends mutating access, prohibiting any access to the argument.
+* A `consuming` parameter-convention is illegal, since that ends the lifetime of the argument immediately.
+
+If the `ArgType` is `~Escapable`, then it can have a pre-existing lifetime dependency.
+In this case, the semantics of `@dependsOn()` are slightly different:
+* A `consuming` parameter-convention will copy the lifetime dependency from the argument to the result
+* A `borrowing` or `inout` parameter-convention can either copy the lifetime dependency or create a new scoped lifetime dependency.
+  In this case, for reasons explained earlier, we default to copying the lifetime dependency.
+  If a scoped lifetime dependency is needed, it can be explicitly requested by adding the `scoped` keyword:
+  
+```swift
+func f(arg: borrowing ArgType) -> @dependsOn(scoped arg) ResultType
+```
 
 **Methods:** Similar rules apply to `self` lifetime dependencies on methods.
 Given a method of this form:
 
-```
-<mutation-modifier> func method(... args ...) -> <lifetime-type>(self) ResultType
+```swift
+<mutation-modifier> func method(... args ...) -> @dependsOn(self) ResultType
 ```
 
-We only permit
-
-* A `borrow(self)` lifetime dependency with a `borrowing` mutation-modifier
-* A `mutate(self)` lifetime dependency with a `mutating` mutation-modifier
-* A `consume(self)` lifetime dependency with a `consuming` mutation-modifier
-* A `copy(self)` lifetime dependency with a `borrowing` or `mutating` mutation-modifier
-
-The rules above apply regardless of whether the parameter-convention or mutation-modifier is explicitly written or is implicit.
+The behavior depends as above on the mutation-modifier and whether the defining type is `Escapable` or `~Escapable`.
 
 **Initializers:** An initializer can define a lifetime dependency on one of its arguments.
-In this case, the rules are the same as for “Functions” above:
+In this case, we use the same rules same as for “Functions” above
+by using the convention that initializers can be viewed as functions that return `Self`:
 
-```
-init(arg: <parameter-convention> ArgType) -> <lifetime-type>(arg) Self
+```swift
+init(arg: <parameter-convention> ArgType) -> @dependsOn(arg) Self
 ```
 
 ### Implicit Lifetime Dependencies
 
 The syntax above allows developers to explicitly annotate lifetime dependencies in their code.
-But because the possibilities are limited, we can usually allow the compiler to infer the dependency.
+But because the possibilities are limited, we can usually allow the compiler to infer a suitable dependency.
 The detailed rules are below, but generally we require that the return type be `~Escapable` and that there be one “obvious” source for the dependency.
 
-In particular, for methods, whenever there is an explicit mutation type, we can infer the matching lifetime dependency on `self`:
+In particular, we can infer a lifetime dependency on `self` for any method that returns a `~Escapable` type.
+As above, the details vary depending on whether `self` is `Escapable` or `~Escapable`:
 
-```
-struct NonEscapableType: ~Escapable { ... }
-struct S {
-  borrowing func f(...) -> /* borrow(self) */ NonEscapableType
-  mutating func f(...) -> /* mutate(self) */ NonEscapableType
-  consuming func f(...) -> /* consume(self) */ NonEscapableType
+```swift
+struct NonescapableType: ~Escapable { ... }
+struct EscStruct {
+  func f1(...) -> /* @dependsOn(self) */ NonescapableType
+  borrowing func f2(...) -> /* @dependsOn(self) */ NonescapableType
+  mutating func f3(...) -> /* @dependsOn(self) */ NonescapableType
+
+  // Note: no lifetime dependency is inferred for a consuming method
+  // on an `Escapable` type, since there is no legal option
+  consuming func f4(...) -> NonescapableType
+}
+
+struct NEStruct: ~Escapable {
+  func f1(...) -> /* @dependsOn(self) */ NonescapableType
+  borrowing func f2(...) -> /* @dependsOn(self) */ NonescapableType
+  mutating func f3(...) -> /* @dependsOn(self) */ NonescapableType
+
+  // Note: A copy lifetime dependency is legal here
+  consuming func f4(...) -> /* @dependsOn(self) */ NonescapableType
+}
 ```
 
-For free or static functions or initializers, we can infer when there is one obvious argument to serve as the source of the dependency.
-Specifically, we’ll do this when there is one argument that is `~Escapable` or `~Copyable` (these are the types that already have lifetime restrictions, so are the natural types to expect for this role) and has an explicit parameter convention.
+For free or static functions or initializers, we can infer a lifetime dependency when the return value is `~Escapable` and there is only one obvious argument that can serve as the source of the dependency.
 For example:
 
-```
-struct Type1: ~Copyable /* Or: ~Escapable */ /* Or: ~Copyable & ~Escapable */
-struct Type2: ~Escapable { ... }
-func f(..., arg1: borrowing Type1, ...) -> /* borrow(arg1) */ Type2
-func f(..., arg1: consuming Type1, ...) -> /* consume(arg1) */ Type2
-func f(..., arg1: inout Type1, ...) -> /* mutate(arg1) */ Type2
+```swift
+struct NEType: ~Escapable { ... }
+
+// If there is only one argument with an explicit parameter convention:
+func f(..., arg1: borrowing Type1, ...) -> /* @dependsOn(arg1) */ NEType
+
+// Or there is only one argument that is `~Escapable`:
+func g(..., arg2: NEType, ...) -> /* @dependsOn(arg2) */ NEType
+
+// If there are multiple possible arguments that we might depend
+// on, we require an explicit dependency:
+// 🛑 Cannot infer lifetime dependency since `arg1` and `arg2` are both candidates
+func g(... arg1: borrowing Type1, arg2: NEType, ...) -> NEType
 ```
 
 We expect these implicit inferences to cover most cases, with the explicit form only occasionally being necessary in practice.
@@ -254,84 +282,75 @@ This modifies *function-result* in the Swift grammar as follows:
 
 >
 > *function-signature* → *parameter-clause* **`async`***?* **`throws`***?* *function-result**?* \
-> *function-signature* → *parameter-clause* **`async`***?* **`rethrows`** *function-result**?* \
-> *function-result* → **`->`** *attributes**?* *lifetime-modifiers**?* *type*
-> *lifetime-modifiers* **`->`** *lifetime-modifier* *lifetime-modifiers**?*
-> *lifetime-modifier* **`->`** *lifetime-modifier-type* **`(`** **`self`** `**)**` \
-> *lifetime-modifier* **`->`** *lifetime-modifier-type* **`(`** *external-parameter-name* `**)**` \
-> *lifetime-modifier* **`->`** *lifetime-modifier-type* **`(`** *parameter-index* `**)**` 
-> *lifetime-modifier-type* **`->`** **`copy`** | **`borrow`** | **`mutate`** | **`consume`**
+> *function-signature* → *parameter-clause* **`async`***?* **`rethrows`** *function-result**?*
+> *function-result* → **`->`** *attributes?* *lifetime-modifiers?* *type*
+> *lifetime-modifiers* **`->`** *lifetime-modifier* *lifetime-modifiers?*
+> *lifetime-modifier* **`->`** **`@dependsOn`** **`(`** *lifetime-dependency* **`)`**
+> *lifetime-dependency* **`->`** **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name*
 >
 
-Here, the argument to the lifetime modifier must be one of the following:
-
-* *local-parameter-name:* the local name of one of the function parameters,
-* *parameter-index:* a numeric index of one of the parameters in the *parameter-clause* (the first parameter is number zero), or
-* the token **`self`**.
+Here, the *lifetime-dependency* argument to the lifetime modifier must be one of the following:
 
-Additionally, the argument referred to by the *external-parameter-name* or *parameter-index* must have an explicit *parameter-modifier* of `inout`, `borrowing`, or `consuming`.
-If the *lifetime-modifier* is the token `**self**`**,** then the method must have a *mutation-modifier* of `mutating`, `borrowing`, or `consuming`.
+* *local-parameter-name*: the local name of one of the function parameters, or
+* the token **`self`**, or
+* either of the above preceded by the **`scoped`** keyword
 
 #### Initializers
 
 Initializers can have arguments, and there are cases where users will want to specify a lifetime dependency between one or more arguments and the constructed value.
-We propose allowing initializers to write out an explicit return clause for this case:
+We propose allowing initializers to write out an explicit return clause for this case.
+The return type must be exactly the token `Self` or the token sequence `Self?` in the case of a failable initializer:
 
-```
+```swift
 struct S {
-  init(arg1: Type1) -> borrow(arg1) Self
+  init(arg1: Type1) -> @dependsOn(arg1) Self
+  init?(arg2: Type2) -> @dependsOn(scoped arg2) Self?
 }
 ```
 
-This syntax will be rejected if the return type is not exactly the token `Self`.
-
 > Grammar of an initializer declaration:
 >
 > *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`throws`***?* *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body* \
 > *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`rethrows`** *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body*
-> *initializer-lifetime-modifier* → `**->**` *lifetime-modifiers* ** **`Self`**
+> *initializer-lifetime-modifier* → `**->**` *lifetime-modifiers* ** **`Self`** \
+> *initializer-lifetime-modifier* → `**->**` *lifetime-modifiers* ** **`Self?`**
 
 ### Inference Rules
 
 If there is no explicit lifetime dependency, we will automatically infer one according to the following rules:
 
-**For methods where the return type is `~Escapable` and there is an explicit mutation type**, we will infer a dependency against self, depending on the mutation type of the function.
+**For methods where the return type is `~Escapable`**, we will infer a dependency against self, depending on the mutation type of the function.
 Note that this is not affected by the presence, type, or modifier of any other arguments to the method.
-Specifically, we will infer:
-
-* a `borrow` lifetime dependency for a method that borrows `self`
-* a `mutate` lifetime dependency for a method that is `mutating` on self
-* a `consume` lifetime dependency for a method that is `consuming` on self
 
 **For a free or static functions or initializers with at least one argument,** we will infer a lifetime dependency when all of the following are true:
 
 * the return type is `~Escapable`,
-* there is exactly one argument that is either `~Copyable` or `~Escapable`
-* that argument has an explicit `borrowing`, `consuming`, or `inout` convention specified
+* there is exactly one argument that satisfies any of the following:
+** is either `~Copyable` or `~Escapable`
+** is `Escapable` and `Copyable` and has an explicit `borrowing`, `consuming`, or `inout` convention specified
 
-In this case, the compiler will infer:
-
-* a `borrow` lifetime dependency for a function whose only `~Escapable` or `~Copyable` argument is `borrowing` 
-* a `mutate` lifetime dependency for a function whose only `~Escapable` or `~Copyable` argument is `inout`
-* a `consume` lifetime dependency for a function whose only `~Escapable` or `~Copyable` argument is `consuming`
+In this case, the compiler will infer a dependency on the unique argument identified by this last set of conditions.
 
 **In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
 If a function, method, or initializer has a `~Escapable` return type, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
 
 ### Semantics
 
-The syntax above declares a lifetime dependency between the return value of a function or method and a function argument, method argument, or `self`.
+The previous sections detail how lifetime dependency between the return value of a function or method and a function argument, method argument, or `self` can be explicitly declared or implicitly inferred by the compiler.
+
+When the dependency involves a function, method, or initializer argument,
+if the corresponding argument is `borrowing` or `inout` then we can refer to that argument as the *source* of the dependency, and the return value then has a *scoped lifetime dependency* on the source.
+When this occurs, the compiler may shorten the lifetime of the return value or extend the lifetime of the source value within the existing language rules in order to satisfy the requirements below.
+Further, the compiler will issue diagnostics if these requirements cannot be satisfied:
 
-If the `lifetime-modifier` (either specified or inferred) is `borrow` or `mutate`, then we can refer to the argument or `self` as the *source* of the dependency, and the return value then has respectively a *borrow* *lifetime dependency* or a *mutate lifetime dependency* ** on the source.
-When this occurs, the compiler may shorten the lifetime of the return value or extend the lifetime of the source value within the existing language rules in order to meet the requirement.
-Further, the compiler will issue diagnostics in the following cases:
+* The return value must be destroyed before the source value.
+  This can be obstructed if there are other factors (such as nested scopes, function returns, or closure captures) that contradict the lifetime dependency.
+* For a borrowing argument, the source value cannot be mutated before the return value is destroyed.
+* For an inout argument, the source value is accessed or mutated before the return value is destroyed.
 
-* If the return value cannot be destroyed before the source value.
-This can happen if there are other factors (such as nested scopes, function returns, or closure captures) that contradict the lifetime dependency.
-* For a borrow lifetime dependency, if the source value is mutated before the return value is destroyed.
-* For a mutate lifetime dependency, if the source value is accessed or mutated before the return value is destroyed.
+The rules above apply with the obvious modifications for a method that explicitly or implicitly has a lifetime dependency between the return value and `self`.
 
-If the `lifetime-modifier` is `consume` or `copy`, then the return value from the function or method gains the same lifetime dependency as the function argument, method argument, or `self`.
+If the `lifetime-kind` is `consume` or `copy`, then the return value from the function or method gains the same lifetime dependency as the function argument, method argument, or `self`.
 In this case, we’ll refer to the argument or `self` as the *original* value.
 In this case, the original value must itself must be `~Escapable`, and must in turn have a borrow or mutate lifetime dependency on some other source value.
 The return value will then have a borrow or mutate lifetime dependency on that same source value that will be enforced by the compiler as above.
@@ -342,7 +361,7 @@ The lifetime dependencies described in this document can be applied only to `~Es
 Further, any return value that is `~Escapable` must have a lifetime dependency.
 In particular, this implies that the initializer for a non-escapable type must have at least one argument.
 
-```
+```swift
 struct S: ~Escapable {
   init() {} // 🛑 Error: ~Escapable return type must have lifetime dependency
 }
@@ -353,8 +372,8 @@ struct S: ~Escapable {
 Everything discussed here is additive to the existing Swift grammar and type system.
 It has no effect on existing code.
 
-The tokens `-> borrowing` in a function declaration might indicate the beginning of a borrowing lifetime annotation or could indicate that the function returns an existing type called `borrowing`.
-This ambiguity can be fully resolved in the parser by looking for an open parenthesis `(` after the `borrowing`, `mutating`, `copy`, or `consume` token.
+The tokens `-> dependsOn` in a function declaration might indicate the beginning of a borrowing lifetime annotation or could indicate that the function returns an existing type called `dependsOn`.
+This ambiguity can be fully resolved in the parser by looking for an open parenthesis `(` after the `dependsOn` token.
 
 ## Effect on ABI stability
 
@@ -372,52 +391,24 @@ Removing a lifetime dependency constraint only affects existing source code in t
 We propose above putting the annotation on the return value, which we believe matches the intuition that the method or property is producing this lifetime dependence alongside the returned value.
 It would also be possible to put an annotation on the parameters instead:
 
-```
+```swift
 func f(@resultDependsOn arg1: Array<Int>) -> BufferReference<Int>
 ```
 
 Depending on the exact language in use, it could also be more natural to put the annotation after the return value.
 However, we worry that this hides this critical information in cases where the return type is longer or more complex.
 
-```
+```swift
 func f(arg1: Array<Int>) -> BufferReference<Int> dependsOn(arg1)
 ```
 
 ### Different spellings
 
-We propose above using the existing `borrow`/`mutate`/`consume`/`copy` keywords, since we feel the new behaviors have a substantial similarity to how similar keywords are used elsewhere in the language.
-
-We also considered `borrowing`/`mutating`/`consuming`/`copying` but felt that the semantic differences merited using a different form of these words.
-
-We could have a single `scoped` annotation that covers the `borrow` and `mutate` semantics described above,
-since the semantics are implied by the argument.
-Similarly we could collapse `copy` and `consume` to use just `copy` (since they are formally identical).
-That would give us two notations rather than the four in our current proposal:
-```
-// `borrow` and `mutate` semantics could share a single annotation:
-func f(arg1: borrow Array<Int>) -> scoped(arg1) BufferReference<Int> // Same as `borrow(arg1)`
-func f(arg1: inout Array<Int>) -> scoped(arg1) BufferReference<Int> // Same as `mutate(arg1)`
-```
-
-This single `scoped` notation would prevent us from eventually supporting the
-“Downgraded dependencies” described below.
-The `scoped` notation could also be spelled `@scoped` or `@dependsOn`.
-
-#### Implicit argument convention or method mutation modifier
-
-The Detailed design above requires that any function, method, or property that returns a `~Escapable` type must have an implicit or explicit lifetime constraint.
-Further, it requires that any lifetime constraint refer to an argument with an *explicit* mutation convention or `self` where the method has an *explicit* mutation modifier.
-For example:
-
-```
-func f(arg1: Type1) -> borrow(arg1) NonEscapableType // 🛑 `arg1` must be marked `borrowing`
-
-... Type ... {
-  func f() -> borrow(self) Self // 🛑 method must be marked `borrowing`
-}
+An earlier version of this proposal advocated using the existing `borrow`/`mutate`/`consume`/`copy` keywords to specify a particular lifetime dependency semantic:
+```swift
+func f(arg1: borrow Array<Int>) -> borrow(arg1) BufferReference<Int>
 ```
-
-Requiring an explicit mutation specification seems to us to improve readability, but could potentially be dropped by relying on Swift’s usual default argument and method conventions.
+This was changed after we realized that there was in practice almost always a single viable semantic for any given situation, so the additional refinement seemed unnecessary.
 
 ## Future Directions
 
@@ -428,7 +419,7 @@ There is some ambiguity here, since resilience hides the distinction between a c
 In particular, the resilience concern might prevent us from inferring lifetime dependencies for properties across module boundaries.
 The notation for an explicit lifetime dependency on a property might look like the following:
 
-```
+```swift
 struct Container {
   var view: ReturnType { borrowing get }
 }
@@ -449,25 +440,13 @@ It also helps simplify the enforcement of lifetime constraints by guaranteeing t
 Most importantly, this restriction helps ensure that the new semantics (especially lifetime dependency inference) cannot accidentally break existing code.
 We expect that in the future, additional investigation can reveal a way to relax this restriction.
 
-#### Downgraded Dependencies
-
-```
-// This is forbidden by the current proposal, but could be supported in theory
-func f(arg1: inout Array<Int>) -> borrow BufferReference<Int>
-```
-
-Our current proposal requires that `inout` arguments only be used with `mutate` lifetime dependencies (or `copy` if the argument is itself `~Escapable`).
-It may be useful to permit “downgrading” the access so that the function can have mutating access to the argument while it is running, but only extends read-only `borrow` access to the return value.
-We are not confident that we can make this fully safe today:  With our current diagnostic work, we cannot prevent the implementor of `f` from “sneaking” read-write access into the returned value.
-We hope to expand these diagnostics in the future, at which point we may be able to safely lift this restriction.
-
 #### Lifetime Dependencies between arguments
 
 A caller may need assurance that a callee will honor a lifetime dependency between two arguments.
 For example, if a function is going to destroy a container and a reference to that container in the process of computing some result,
 it needs to guarantee that the reference is destroyed before the container:
-```
-func f(container: consuming ContainerType, ref: borrow(container) consuming RefType) -> ResultType
+```swift
+func f(container: consuming ContainerType, ref: @dependsOn(container) consuming RefType) -> ResultType
 ```
 
 #### Lifetime Dependencies for Tuples
@@ -484,10 +463,19 @@ We expect to address this in the near future in a separate proposal.
 It should be possible to return containers with collections of lifetime-constrained elements.
 For example, a container may want to return a partition of its contents:
 ```swift
-borrowing func chunks(n: Int) -> borrow(self) SomeList<borrow(self) BufferView<UInt8>>
+borrowing func chunks(n: Int) -> @dependsOn(self) SomeList<@dependsOn(self) StorageView<UInt8>>
 ```
 We're actively looking into ways to support these more involved cases and expect to address this in a future proposal.
 
+#### Parameter index for lifetime dependencies
+
+Internally, the implementation records dependencies based on the parameter index.
+This could be exposed as an alternate spelling if there were sufficient demand.
+
+```swift
+func f(arg1: Type1, arg2: Type2, arg3: Type3) -> @dependsOn(0) ReturnType
+```
+
 ## Acknowledgements
 
 Dima Galimzianov provided several examples for Future Directions.

From 6ebcdb4fefbe51842040a30c85b07e4d6c13708e Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Thu, 21 Mar 2024 15:13:51 -0700
Subject: [PATCH 12/59] Corrections from meg-gupta

---
 proposals/NNNN-lifetime-dependency.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index b8e3213c2e..50b303cecc 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -134,7 +134,7 @@ Similar to the previous example:
 
 In both this and the previous case, the lifetime of the return value is "scoped" to the lifetime of the original value.
 Because lifetime dependencies can only be attached to `~Escapable` values, types that contain pointers will generally need to be `~Escapable` in order to provide safe semantics.
-As a result, **scoped lifetime dependencies** are the common case whenever an `Escapable` value (such as an Array or similar container) is providing a `~Escapable` value (such as the `BufferReference` or `MutatingBufferReference` in these examples).
+As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as an Array or similar container) is providing a `~Escapable` value (such as the `BufferReference` or `MutatingBufferReference` in these examples).
 
 #### Copy Lifetime Dependency
 
@@ -214,7 +214,7 @@ Given a method of this form:
 
 The behavior depends as above on the mutation-modifier and whether the defining type is `Escapable` or `~Escapable`.
 
-**Initializers:** An initializer can define a lifetime dependency on one of its arguments.
+**Initializers:** An initializer can define lifetime dependencies on one or more arguments.
 In this case, we use the same rules same as for “Functions” above
 by using the convention that initializers can be viewed as functions that return `Self`:
 

From eed1b0576d17f19db2f91e38df1e31bda2bb48e0 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Fri, 22 Mar 2024 10:41:42 -0700
Subject: [PATCH 13/59] Overhaul semantics discussion

We need to separate description of the dependency itself --
which places a bound on when particular objects can be
destroyed -- from the syntax.
In particular, the syntax specifies a relationship between
two objects, but that relationship is not always a
lifetime dependency itself (because of "copied" dependencies).
---
 proposals/NNNN-lifetime-dependency.md | 119 +++++++++++++++-----------
 1 file changed, 69 insertions(+), 50 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 50b303cecc..c65ef39de9 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -238,8 +238,8 @@ struct EscStruct {
   borrowing func f2(...) -> /* @dependsOn(self) */ NonescapableType
   mutating func f3(...) -> /* @dependsOn(self) */ NonescapableType
 
-  // Note: no lifetime dependency is inferred for a consuming method
-  // on an `Escapable` type, since there is no legal option
+  // 🛑 Error: there is no valid lifetime dependency for
+  // a consuming method on an `Escapable` type
   consuming func f4(...) -> NonescapableType
 }
 
@@ -275,6 +275,33 @@ We expect these implicit inferences to cover most cases, with the explicit form
 
 ## Detailed design
 
+### Relation to ~Escapable
+
+The lifetime dependencies described in this document can be applied only to `~Escapable` return values.
+Further, any return value that is `~Escapable` must have a lifetime dependency.
+In particular, this implies that the initializer for a non-escapable type must have at least one argument.
+
+```swift
+struct S: ~Escapable {
+  init() {} // 🛑 Error: ~Escapable return type must have lifetime dependency
+}
+```
+
+### Basic Semantics
+
+A lifetime dependency annotation creates a *lifetime dependency* between a *dependent value* and a *source value*.
+This relationship obeys the following requirements:
+
+* The dependent value must be nonescapable.
+
+* The dependent value's lifetime must not be longer than that of the source value.
+
+* The dependent value is treated as an ongoing access to the source value.
+  Following Swift's usual exclusivity rules, the source value may not be mutated during the lifetime of the dependent value;
+  if the access is a mutating access, the source value is further prohibited from being accessed at all during the lifetime of the dependent value.
+
+The compiler must issue a diagnostic if any of the above cannot be satisfied.
+
 ### Grammar
 
 This new syntax adds an optional lifetime modifier just before the return type.
@@ -282,39 +309,67 @@ This modifies *function-result* in the Swift grammar as follows:
 
 >
 > *function-signature* → *parameter-clause* **`async`***?* **`throws`***?* *function-result**?* \
-> *function-signature* → *parameter-clause* **`async`***?* **`rethrows`** *function-result**?*
-> *function-result* → **`->`** *attributes?* *lifetime-modifiers?* *type*
-> *lifetime-modifiers* **`->`** *lifetime-modifier* *lifetime-modifiers?*
-> *lifetime-modifier* **`->`** **`@dependsOn`** **`(`** *lifetime-dependency* **`)`**
-> *lifetime-dependency* **`->`** **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name*
+> *function-signature* → *parameter-clause* **`async`***?* **`rethrows`** *function-result**?* \
+> *function-result* → **`->`** *attributes?* *lifetime-modifiers?* *type* \
+> *lifetime-modifiers* → **`->`** *lifetime-modifier* *lifetime-modifiers?* \
+> *lifetime-modifier* → **`->`** **`@dependsOn`** **`(`** *lifetime-dependent* **`)`** \
+> *lifetime-dependent* → **`->`** **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name*
 >
 
-Here, the *lifetime-dependency* argument to the lifetime modifier must be one of the following:
+The *lifetime-dependent* argument to the lifetime modifier is one of the following:
 
 * *local-parameter-name*: the local name of one of the function parameters, or
 * the token **`self`**, or
 * either of the above preceded by the **`scoped`** keyword
 
+This modifier creates a lifetime dependency with the return value used as the dependent value.
+The return value must be nonescapable.
+
+The source value of the resulting dependency can vary.
+In some cases, the source value will be the named parameter or `self` directly.
+However, if the corresponding named parameter or `self` is nonescapable, then that value will itself have an existing lifetime dependency and thus the new dependency might "copy" the source of that existing dependency.
+
+The following table summarizes the possibilities, which depend on the type and mutation modifier of the argument or `self` and the existence of the `scoped` keyword.
+Here, "scoped" indicates that the dependent gains a direct lifetime dependency on the named parameter or `self` and "copied" indicates that the dependent gains a lifetime dependency on the source of an existing dependency:
+
+| mutation modifier  | argument type | without `scoped` | with `scoped` |
+| ------------------ | ------------- | ---------------- | ------------- |
+| borrowed           | escapable     | scoped           | scoped        |
+| inout or mutating  | escapable     | scoped           | scoped        |
+| consuming          | escapable     | Illegal          | Illegal       |
+| borrowed           | nonescapable  | copied           | scoped        |
+| inout or mutating  | nonescapable  | copied           | scoped        |
+| consuming          | nonescapable  | copied           | Illegal       |
+
+Two observations may help in understanding the table above:
+* An escapable argument cannot have a pre-existing lifetime dependency, so copying is never possible in those cases.
+* A consumed argument cannot be the source of a lifetime dependency that will outlive the function call, so only copying is legal in that case.
+
+**Note**: In practice, the `scoped` modifier keyword is likely to be only rarely used.  The rules above were designed to support the known use cases without requiring such a modifier.
+
 #### Initializers
 
-Initializers can have arguments, and there are cases where users will want to specify a lifetime dependency between one or more arguments and the constructed value.
-We propose allowing initializers to write out an explicit return clause for this case.
+Since nonescapable values cannot be returned without a lifetime dependency,
+initializers for such types must specify a lifetime dependency on one or more arguments.
+We propose allowing initializers to write out an explicit return clause for this case, which permits the use of the same syntax as functions or methods.
 The return type must be exactly the token `Self` or the token sequence `Self?` in the case of a failable initializer:
 
 ```swift
 struct S {
   init(arg1: Type1) -> @dependsOn(arg1) Self
-  init?(arg2: Type2) -> @dependsOn(scoped arg2) Self?
+  init?(arg2: Type2) -> @dependsOn(arg2) Self?
 }
 ```
 
 > Grammar of an initializer declaration:
 >
 > *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`throws`***?* *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body* \
-> *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`rethrows`** *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body*
+> *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`rethrows`** *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body* \
 > *initializer-lifetime-modifier* → `**->**` *lifetime-modifiers* ** **`Self`** \
 > *initializer-lifetime-modifier* → `**->**` *lifetime-modifiers* ** **`Self?`**
 
+The implications of mutation modifiers and argument type on the resulting lifetime dependency exactly follow the rules above for functions and methods.
+
 ### Inference Rules
 
 If there is no explicit lifetime dependency, we will automatically infer one according to the following rules:
@@ -326,55 +381,19 @@ Note that this is not affected by the presence, type, or modifier of any other a
 
 * the return type is `~Escapable`,
 * there is exactly one argument that satisfies any of the following:
-** is either `~Copyable` or `~Escapable`
-** is `Escapable` and `Copyable` and has an explicit `borrowing`, `consuming`, or `inout` convention specified
+  - is either `~Copyable` or `~Escapable`
+  - has an explicit `borrowing`, `consuming`, or `inout` convention specified
 
 In this case, the compiler will infer a dependency on the unique argument identified by this last set of conditions.
 
 **In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
 If a function, method, or initializer has a `~Escapable` return type, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
 
-### Semantics
-
-The previous sections detail how lifetime dependency between the return value of a function or method and a function argument, method argument, or `self` can be explicitly declared or implicitly inferred by the compiler.
-
-When the dependency involves a function, method, or initializer argument,
-if the corresponding argument is `borrowing` or `inout` then we can refer to that argument as the *source* of the dependency, and the return value then has a *scoped lifetime dependency* on the source.
-When this occurs, the compiler may shorten the lifetime of the return value or extend the lifetime of the source value within the existing language rules in order to satisfy the requirements below.
-Further, the compiler will issue diagnostics if these requirements cannot be satisfied:
-
-* The return value must be destroyed before the source value.
-  This can be obstructed if there are other factors (such as nested scopes, function returns, or closure captures) that contradict the lifetime dependency.
-* For a borrowing argument, the source value cannot be mutated before the return value is destroyed.
-* For an inout argument, the source value is accessed or mutated before the return value is destroyed.
-
-The rules above apply with the obvious modifications for a method that explicitly or implicitly has a lifetime dependency between the return value and `self`.
-
-If the `lifetime-kind` is `consume` or `copy`, then the return value from the function or method gains the same lifetime dependency as the function argument, method argument, or `self`.
-In this case, we’ll refer to the argument or `self` as the *original* value.
-In this case, the original value must itself must be `~Escapable`, and must in turn have a borrow or mutate lifetime dependency on some other source value.
-The return value will then have a borrow or mutate lifetime dependency on that same source value that will be enforced by the compiler as above.
-
-### Relation to ~Escapable
-
-The lifetime dependencies described in this document can be applied only to `~Escapable` return values.
-Further, any return value that is `~Escapable` must have a lifetime dependency.
-In particular, this implies that the initializer for a non-escapable type must have at least one argument.
-
-```swift
-struct S: ~Escapable {
-  init() {} // 🛑 Error: ~Escapable return type must have lifetime dependency
-}
-```
-
 ## Source compatibility
 
 Everything discussed here is additive to the existing Swift grammar and type system.
 It has no effect on existing code.
 
-The tokens `-> dependsOn` in a function declaration might indicate the beginning of a borrowing lifetime annotation or could indicate that the function returns an existing type called `dependsOn`.
-This ambiguity can be fully resolved in the parser by looking for an open parenthesis `(` after the `dependsOn` token.
-
 ## Effect on ABI stability
 
 Lifetime dependency annotations may affect how values are passed into functions, and thus adding or removing one of these annotations should generally be expected to affect the ABI.

From 2e82c6ba50320a968d244d61e1e2021e0795d058 Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Mon, 25 Mar 2024 17:17:23 -0700
Subject: [PATCH 14/59] Use "nonescapable" for the concept, rather than
 `~Escapable`

---
 proposals/NNNN-lifetime-dependency.md | 66 +++++++++++++--------------
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index c65ef39de9..b6a5ea6edf 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -63,16 +63,16 @@ These lifetime dependencies can be expressed in several different ways, with var
 
 ### Background: "Escapable" and “Nonescapable” Types
 
-In order to avoid changing the meaning of existing code, we will introduce two complementary type constraints:
-`Escapable` and `~Escapable`.
-These constraints can appear in a type declaration as a protocol.
+In order to avoid changing the meaning of existing code, we will introduce a
+new protocol `Escapable` which can be suppressed with `~Escapable`.
 
 Normal Swift types are `Escapable` by default.
 This implies that they can be returned, stored in properties, or otherwise "escape" the local context.
-Conversely, types explicitly declared `~Escapable` are not allowed to escape the local context except in very specific circumstances.
-A separate proposal explains the general syntax and semantics of `Escapable` and `~Escapable` types.
+Conversely, types can be explicitly declared to be "nonescapable" using `~Escapable`.
+These types are not allowed to escape the local context except in very specific circumstances.
+A separate proposal explains the general syntax and semantics of `Escapable` and `~Escapable`.
 
-By themselves, `~Escapable` types have severe constraints on usage.
+By themselves, nonescapable types have severe constraints on usage.
 For example, consider a hypothetical `BufferReference` type that is similar to the standard library `UnsafeBufferPointer` or the `StorageView` type that is being proposed for inclusion in the standard library.
 It simply holds a pointer and size and can be used to access data stored in a contiguous block of memory.
 (We are not proposing this type; it is shown here merely for illustrative purposes.)
@@ -85,7 +85,7 @@ struct BufferReference<T>: ~Escapable {
 ```
 
 Because this type is marked `~Escapable`, it cannot be returned from a function or even initialized without some way to relax the escapability restrictions.
-This proposal provides a set of constraints that can tie the lifetime of a `~Escapable` value to the lifetime of some other value.
+This proposal provides a set of constraints that can tie the lifetime of a nonescapable value to the lifetime of some other value.
 In the most common cases, these constraints can be inferred automatically.
 
 ### Explicit Lifetime Dependency Annotations
@@ -133,12 +133,12 @@ Similar to the previous example:
 * No other read or write access to the array will be allowed for as long as the returned value exists.
 
 In both this and the previous case, the lifetime of the return value is "scoped" to the lifetime of the original value.
-Because lifetime dependencies can only be attached to `~Escapable` values, types that contain pointers will generally need to be `~Escapable` in order to provide safe semantics.
-As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as an Array or similar container) is providing a `~Escapable` value (such as the `BufferReference` or `MutatingBufferReference` in these examples).
+Because lifetime dependencies can only be attached to nonescapable values, types that contain pointers will generally need to be nonescapable in order to provide safe semantics.
+As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as an Array or similar container) is providing a nonescapable value (such as the `BufferReference` or `MutatingBufferReference` in these examples).
 
 #### Copy Lifetime Dependency
 
-The case where a `~Escapable` value is used to produce a different `~Escapable` value is somewhat different.
+The case where a nonescapable value is used to produce another nonescapable value is somewhat different.
 Here's a typical example that constructs a new `BufferReference` from an existing one:
 ```swift
 struct BufferReference<T>: ~Escapable {
@@ -148,8 +148,8 @@ struct BufferReference<T>: ~Escapable {
 }
 ```
 
-In this examples, the `~Escapable` result depends on a `~Escapable` value.
-Recall that `~Escapable` values such as these represent values that are already lifetime-constrained to another value.
+In this examples, the nonescapable result depends on a nonescapable value.
+Recall that nonescapable values such as these represent values that are already lifetime-constrained to another value.
 
 For a `consuming` method, the return value cannot have a scoped lifetime dependency on the original value, since the original value no longer exists when the method returns.
 Instead, the return value must "copy" the lifetime dependency from the original:
@@ -182,11 +182,11 @@ func f(arg: <parameter-convention> ArgType) -> @dependsOn(arg) ResultType
 Where
 
 *  *`parameter-convention`* is one of the ownership specifiers **`borrowing`**, **`consuming`**, or **`inout`**, (this may be implied by Swift’s default parameter ownership rules),
-* `ResultType` must be `~Escapable`.
+* `ResultType` must be nonescapable.
 
-If the `ArgType` is `Escapable`, the return value will have a new scoped dependency on the argument.
-(This is the only possibility, as an `Escapable` value cannot have an existing lifetime dependency,
-so we cannot copy it.)
+If the `ArgType` is escapable, the return value will have a new scoped dependency on the argument.
+(This is the only possibility, as an escapable value cannot have an existing lifetime dependency,
+so we cannot copy the lifetime dependency.)
 A scoped dependency ensures the argument will not be destroyed while the result is alive.
 Also, access to the argument will be restricted for the lifetime of the result following Swift's usual exclusivity rules:
 
@@ -194,7 +194,7 @@ Also, access to the argument will be restricted for the lifetime of the result f
 * An `inout` parameter-convention extends mutating access, prohibiting any access to the argument.
 * A `consuming` parameter-convention is illegal, since that ends the lifetime of the argument immediately.
 
-If the `ArgType` is `~Escapable`, then it can have a pre-existing lifetime dependency.
+If the `ArgType` is nonescapable, then it can have a pre-existing lifetime dependency.
 In this case, the semantics of `@dependsOn()` are slightly different:
 * A `consuming` parameter-convention will copy the lifetime dependency from the argument to the result
 * A `borrowing` or `inout` parameter-convention can either copy the lifetime dependency or create a new scoped lifetime dependency.
@@ -212,7 +212,7 @@ Given a method of this form:
 <mutation-modifier> func method(... args ...) -> @dependsOn(self) ResultType
 ```
 
-The behavior depends as above on the mutation-modifier and whether the defining type is `Escapable` or `~Escapable`.
+The behavior depends as above on the mutation-modifier and whether the defining type is escapable or nonescapable.
 
 **Initializers:** An initializer can define lifetime dependencies on one or more arguments.
 In this case, we use the same rules same as for “Functions” above
@@ -226,10 +226,10 @@ init(arg: <parameter-convention> ArgType) -> @dependsOn(arg) Self
 
 The syntax above allows developers to explicitly annotate lifetime dependencies in their code.
 But because the possibilities are limited, we can usually allow the compiler to infer a suitable dependency.
-The detailed rules are below, but generally we require that the return type be `~Escapable` and that there be one “obvious” source for the dependency.
+The detailed rules are below, but generally we require that the return type be nonescapable and that there be one “obvious” source for the dependency.
 
-In particular, we can infer a lifetime dependency on `self` for any method that returns a `~Escapable` type.
-As above, the details vary depending on whether `self` is `Escapable` or `~Escapable`:
+In particular, we can infer a lifetime dependency on `self` for any method that returns a nonescapable value.
+As above, the details vary depending on whether `self` is escapable or nonescapable:
 
 ```swift
 struct NonescapableType: ~Escapable { ... }
@@ -253,7 +253,7 @@ struct NEStruct: ~Escapable {
 }
 ```
 
-For free or static functions or initializers, we can infer a lifetime dependency when the return value is `~Escapable` and there is only one obvious argument that can serve as the source of the dependency.
+For free or static functions or initializers, we can infer a lifetime dependency when the return value is nonescapable and there is only one obvious argument that can serve as the source of the dependency.
 For example:
 
 ```swift
@@ -277,9 +277,9 @@ We expect these implicit inferences to cover most cases, with the explicit form
 
 ### Relation to ~Escapable
 
-The lifetime dependencies described in this document can be applied only to `~Escapable` return values.
-Further, any return value that is `~Escapable` must have a lifetime dependency.
-In particular, this implies that the initializer for a non-escapable type must have at least one argument.
+The lifetime dependencies described in this document can be applied only to nonescapable return values.
+Further, any return value that is nonescapable must have a lifetime dependency.
+In particular, this implies that the initializer for a nonescapable type must have at least one argument.
 
 ```swift
 struct S: ~Escapable {
@@ -374,20 +374,20 @@ The implications of mutation modifiers and argument type on the resulting lifeti
 
 If there is no explicit lifetime dependency, we will automatically infer one according to the following rules:
 
-**For methods where the return type is `~Escapable`**, we will infer a dependency against self, depending on the mutation type of the function.
+**For methods where the return value is nonescapable**, we will infer a dependency against self, depending on the mutation type of the function.
 Note that this is not affected by the presence, type, or modifier of any other arguments to the method.
 
 **For a free or static functions or initializers with at least one argument,** we will infer a lifetime dependency when all of the following are true:
 
-* the return type is `~Escapable`,
+* the return value is nonescapable,
 * there is exactly one argument that satisfies any of the following:
-  - is either `~Copyable` or `~Escapable`
+  - is either noncopyable or nonescapable, or
   - has an explicit `borrowing`, `consuming`, or `inout` convention specified
 
 In this case, the compiler will infer a dependency on the unique argument identified by this last set of conditions.
 
 **In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
-If a function, method, or initializer has a `~Escapable` return type, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
+If a function, method, or initializer has a nonescapable return value, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
 
 ## Source compatibility
 
@@ -433,7 +433,7 @@ This was changed after we realized that there was in practice almost always a si
 
 #### Lifetime Dependencies for Computed Properties
 
-It might be useful to allow lifetime dependencies between `self` and the value returned by a computed property.
+It would be useful to allow lifetime dependencies between `self` and the value returned by a computed property.
 There is some ambiguity here, since resilience hides the distinction between a computed and stored property.
 In particular, the resilience concern might prevent us from inferring lifetime dependencies for properties across module boundaries.
 The notation for an explicit lifetime dependency on a property might look like the following:
@@ -449,12 +449,12 @@ extension Type1 {
 ```
 
 Where `borrowing` or `consuming` would indicate that the returned value has a lifetime dependency on `self`.
-We expect that the lifetime notation would be mandatory for any property that provided a `~Escaping` value.
+We expect that the lifetime notation would be mandatory for any property that provided a `~Escapable` value.
 
 #### Lifetime Dependencies for Escapable Types
 
-This proposal has deliberately limited the application of lifetime dependencies to return types that are `~Escapable`.
-This simplifies the model by identifying `~Escapable` types as exactly those types that can carry such dependencies.
+This proposal has deliberately limited the application of lifetime dependencies to return types that are nonescapable.
+This simplifies the model by identifying nonescapable types as exactly those types that can carry such dependencies.
 It also helps simplify the enforcement of lifetime constraints by guaranteeing that constrained values cannot escape before being returned.
 Most importantly, this restriction helps ensure that the new semantics (especially lifetime dependency inference) cannot accidentally break existing code.
 We expect that in the future, additional investigation can reveal a way to relax this restriction.

From f648b02b794c65c5d880635162229608386b76ad Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Mon, 25 Mar 2024 17:28:41 -0700
Subject: [PATCH 15/59] Use "copied lifetime dependency" more consistently

Also, fix the proposed syntax for properties
---
 proposals/NNNN-lifetime-dependency.md | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index b6a5ea6edf..e2da89fa63 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -84,7 +84,7 @@ struct BufferReference<T>: ~Escapable {
 }
 ```
 
-Because this type is marked `~Escapable`, it cannot be returned from a function or even initialized without some way to relax the escapability restrictions.
+Because this type is marked as unconditionally `~Escapable`, it cannot be returned from a function or even initialized without some way to relax the escapability restrictions.
 This proposal provides a set of constraints that can tie the lifetime of a nonescapable value to the lifetime of some other value.
 In the most common cases, these constraints can be inferred automatically.
 
@@ -136,7 +136,7 @@ In both this and the previous case, the lifetime of the return value is "scoped"
 Because lifetime dependencies can only be attached to nonescapable values, types that contain pointers will generally need to be nonescapable in order to provide safe semantics.
 As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as an Array or similar container) is providing a nonescapable value (such as the `BufferReference` or `MutatingBufferReference` in these examples).
 
-#### Copy Lifetime Dependency
+#### Copied Lifetime Dependency
 
 The case where a nonescapable value is used to produce another nonescapable value is somewhat different.
 Here's a typical example that constructs a new `BufferReference` from an existing one:
@@ -215,7 +215,7 @@ Given a method of this form:
 The behavior depends as above on the mutation-modifier and whether the defining type is escapable or nonescapable.
 
 **Initializers:** An initializer can define lifetime dependencies on one or more arguments.
-In this case, we use the same rules same as for “Functions” above
+In this case, we use the same rules as for “Functions” above
 by using the convention that initializers can be viewed as functions that return `Self`:
 
 ```swift
@@ -248,7 +248,7 @@ struct NEStruct: ~Escapable {
   borrowing func f2(...) -> /* @dependsOn(self) */ NonescapableType
   mutating func f3(...) -> /* @dependsOn(self) */ NonescapableType
 
-  // Note: A copy lifetime dependency is legal here
+  // Note: A copied lifetime dependency is legal here
   consuming func f4(...) -> /* @dependsOn(self) */ NonescapableType
 }
 ```
@@ -440,15 +440,14 @@ The notation for an explicit lifetime dependency on a property might look like t
 
 ```swift
 struct Container {
-  var view: ReturnType { borrowing get }
+  var view: @dependsOn(self) ReturnType { get }
 }
 
-extension Type1 {
-  var transformedView: Type1 { consuming get }
+struct Type1: ~Escapable {
+  var childView: @dependsOn(self) Type1 { get }
 }
 ```
 
-Where `borrowing` or `consuming` would indicate that the returned value has a lifetime dependency on `self`.
 We expect that the lifetime notation would be mandatory for any property that provided a `~Escapable` value.
 
 #### Lifetime Dependencies for Escapable Types

From a502076edad9673f14fdef5b6bec1d08b6e7711c Mon Sep 17 00:00:00 2001
From: Tim Kientzle <tkientzle@apple.com>
Date: Fri, 12 Apr 2024 13:49:03 -0700
Subject: [PATCH 16/59] s/@dependsOn/dependsOn/ to match implementation

---
 proposals/NNNN-lifetime-dependency.md | 58 ++++++++++++++-------------
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index e2da89fa63..e643918397 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -14,6 +14,8 @@ To reduce the burden of manually adding such annotations, we also propose inferr
 
 This is a key requirement for the `StorageView` type (previously called `BufferView`) being discussed elsewhere, and is closely related to the proposal for `~Escapable` types.
 
+**Edited** (Apr 12, 2024): Changed `@dependsOn` to `dependsOn` to match the current implementation.
+
 #### See Also
 
 * **TODO**: **** Forum thread discussing this proposal
@@ -97,16 +99,16 @@ Our proposal would allow you to declare an `array.bufferReference()` method as f
 
 ```swift
 extension Array {
-  borrowing func bufferReference() -> @dependsOn(self) BufferReference<Element> {
+  borrowing func bufferReference() -> dependsOn(self) BufferReference<Element> {
     ... construct a BufferReference ...
   }
 }
 ```
 
-The annotation `@dependsOn(self)` here indicates that the returned value must not outlive the array that produced it.
+The annotation `dependsOn(self)` here indicates that the returned value must not outlive the array that produced it.
 Conceptually, it is a continuation of the function's borrowing access:
 the array is being borrowed by the function while the function executes and then continues to be borrowed by the `BufferReference` for as long as the return value exists.
-Specifically, the `@dependsOn(self)` annotation in this example informs the compiler that:
+Specifically, the `dependsOn(self)` annotation in this example informs the compiler that:
 
 * The array must not be destroyed until after the `BufferReference<Element>` is destroyed.
   This ensures that use-after-free cannot occur.
@@ -119,13 +121,13 @@ Let’s consider another hypothetical type: a `MutatingBufferReference<T>` type
 Here's one way such a value might be produced:
 
 ```swift
-func mutatingBufferReference(to: inout Array, count: Int) -> @dependsOn(to) MutatingBufferReference<Element> {
+func mutatingBufferReference(to: inout Array, count: Int) -> dependsOn(to) MutatingBufferReference<Element> {
   ... construct a MutatingBufferReference ...
 }
 ```
 
 We’ve written this example as a free function rather than as a method to show how this annotation syntax can be used to express constraints that apply to a particular argument.
-The `@dependsOn(to)` annotation indicates that the returned value depends on the argument named `to`.
+The `dependsOn(to)` annotation indicates that the returned value depends on the argument named `to`.
 Because `count` is not mentioned in the lifetime dependency, that argument does not participate.
 Similar to the previous example:
 
@@ -143,7 +145,7 @@ Here's a typical example that constructs a new `BufferReference` from an existin
 ```swift
 struct BufferReference<T>: ~Escapable {
   ...
-  consuming func drop(_: Int) -> @dependsOn(self) BufferReference<T> { ... }
+  consuming func drop(_: Int) -> dependsOn(self) BufferReference<T> { ... }
   ...
 }
 ```
@@ -176,7 +178,7 @@ The syntax is somewhat different for functions and methods, though the basic rul
 **Functions:** A simple function with an explicit lifetime dependency annotation generally takes this form:
 
 ```swift
-func f(arg: <parameter-convention> ArgType) -> @dependsOn(arg) ResultType
+func f(arg: <parameter-convention> ArgType) -> dependsOn(arg) ResultType
 ```
 
 Where
@@ -195,21 +197,21 @@ Also, access to the argument will be restricted for the lifetime of the result f
 * A `consuming` parameter-convention is illegal, since that ends the lifetime of the argument immediately.
 
 If the `ArgType` is nonescapable, then it can have a pre-existing lifetime dependency.
-In this case, the semantics of `@dependsOn()` are slightly different:
+In this case, the semantics of `dependsOn()` are slightly different:
 * A `consuming` parameter-convention will copy the lifetime dependency from the argument to the result
 * A `borrowing` or `inout` parameter-convention can either copy the lifetime dependency or create a new scoped lifetime dependency.
   In this case, for reasons explained earlier, we default to copying the lifetime dependency.
   If a scoped lifetime dependency is needed, it can be explicitly requested by adding the `scoped` keyword:
   
 ```swift
-func f(arg: borrowing ArgType) -> @dependsOn(scoped arg) ResultType
+func f(arg: borrowing ArgType) -> dependsOn(scoped arg) ResultType
 ```
 
 **Methods:** Similar rules apply to `self` lifetime dependencies on methods.
 Given a method of this form:
 
 ```swift
-<mutation-modifier> func method(... args ...) -> @dependsOn(self) ResultType
+<mutation-modifier> func method(... args ...) -> dependsOn(self) ResultType
 ```
 
 The behavior depends as above on the mutation-modifier and whether the defining type is escapable or nonescapable.
@@ -219,7 +221,7 @@ In this case, we use the same rules as for “Functions” above
 by using the convention that initializers can be viewed as functions that return `Self`:
 
 ```swift
-init(arg: <parameter-convention> ArgType) -> @dependsOn(arg) Self
+init(arg: <parameter-convention> ArgType) -> dependsOn(arg) Self
 ```
 
 ### Implicit Lifetime Dependencies
@@ -234,9 +236,9 @@ As above, the details vary depending on whether `self` is escapable or nonescapa
 ```swift
 struct NonescapableType: ~Escapable { ... }
 struct EscStruct {
-  func f1(...) -> /* @dependsOn(self) */ NonescapableType
-  borrowing func f2(...) -> /* @dependsOn(self) */ NonescapableType
-  mutating func f3(...) -> /* @dependsOn(self) */ NonescapableType
+  func f1(...) -> /* dependsOn(self) */ NonescapableType
+  borrowing func f2(...) -> /* dependsOn(self) */ NonescapableType
+  mutating func f3(...) -> /* dependsOn(self) */ NonescapableType
 
   // 🛑 Error: there is no valid lifetime dependency for
   // a consuming method on an `Escapable` type
@@ -244,12 +246,12 @@ struct EscStruct {
 }
 
 struct NEStruct: ~Escapable {
-  func f1(...) -> /* @dependsOn(self) */ NonescapableType
-  borrowing func f2(...) -> /* @dependsOn(self) */ NonescapableType
-  mutating func f3(...) -> /* @dependsOn(self) */ NonescapableType
+  func f1(...) -> /* dependsOn(self) */ NonescapableType
+  borrowing func f2(...) -> /* dependsOn(self) */ NonescapableType
+  mutating func f3(...) -> /* dependsOn(self) */ NonescapableType
 
   // Note: A copied lifetime dependency is legal here
-  consuming func f4(...) -> /* @dependsOn(self) */ NonescapableType
+  consuming func f4(...) -> /* dependsOn(self) */ NonescapableType
 }
 ```
 
@@ -260,10 +262,10 @@ For example:
 struct NEType: ~Escapable { ... }
 
 // If there is only one argument with an explicit parameter convention:
-func f(..., arg1: borrowing Type1, ...) -> /* @dependsOn(arg1) */ NEType
+func f(..., arg1: borrowing Type1, ...) -> /* dependsOn(arg1) */ NEType
 
 // Or there is only one argument that is `~Escapable`:
-func g(..., arg2: NEType, ...) -> /* @dependsOn(arg2) */ NEType
+func g(..., arg2: NEType, ...) -> /* dependsOn(arg2) */ NEType
 
 // If there are multiple possible arguments that we might depend
 // on, we require an explicit dependency:
@@ -312,7 +314,7 @@ This modifies *function-result* in the Swift grammar as follows:
 > *function-signature* → *parameter-clause* **`async`***?* **`rethrows`** *function-result**?* \
 > *function-result* → **`->`** *attributes?* *lifetime-modifiers?* *type* \
 > *lifetime-modifiers* → **`->`** *lifetime-modifier* *lifetime-modifiers?* \
-> *lifetime-modifier* → **`->`** **`@dependsOn`** **`(`** *lifetime-dependent* **`)`** \
+> *lifetime-modifier* → **`->`** **`dependsOn`** **`(`** *lifetime-dependent* **`)`** \
 > *lifetime-dependent* → **`->`** **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name*
 >
 
@@ -356,8 +358,8 @@ The return type must be exactly the token `Self` or the token sequence `Self?` i
 
 ```swift
 struct S {
-  init(arg1: Type1) -> @dependsOn(arg1) Self
-  init?(arg2: Type2) -> @dependsOn(arg2) Self?
+  init(arg1: Type1) -> dependsOn(arg1) Self
+  init?(arg2: Type2) -> dependsOn(arg2) Self?
 }
 ```
 
@@ -440,11 +442,11 @@ The notation for an explicit lifetime dependency on a property might look like t
 
 ```swift
 struct Container {
-  var view: @dependsOn(self) ReturnType { get }
+  var view: dependsOn(self) ReturnType { get }
 }
 
 struct Type1: ~Escapable {
-  var childView: @dependsOn(self) Type1 { get }
+  var childView: dependsOn(self) Type1 { get }
 }
 ```
 
@@ -464,7 +466,7 @@ A caller may need assurance that a callee will honor a lifetime dependency betwe
 For example, if a function is going to destroy a container and a reference to that container in the process of computing some result,
 it needs to guarantee that the reference is destroyed before the container:
 ```swift
-func f(container: consuming ContainerType, ref: @dependsOn(container) consuming RefType) -> ResultType
+func f(container: consuming ContainerType, ref: dependsOn(container) consuming RefType) -> ResultType
 ```
 
 #### Lifetime Dependencies for Tuples
@@ -481,7 +483,7 @@ We expect to address this in the near future in a separate proposal.
 It should be possible to return containers with collections of lifetime-constrained elements.
 For example, a container may want to return a partition of its contents:
 ```swift
-borrowing func chunks(n: Int) -> @dependsOn(self) SomeList<@dependsOn(self) StorageView<UInt8>>
+borrowing func chunks(n: Int) -> dependsOn(self) SomeList<dependsOn(self) StorageView<UInt8>>
 ```
 We're actively looking into ways to support these more involved cases and expect to address this in a future proposal.
 
@@ -491,7 +493,7 @@ Internally, the implementation records dependencies based on the parameter index
 This could be exposed as an alternate spelling if there were sufficient demand.
 
 ```swift
-func f(arg1: Type1, arg2: Type2, arg3: Type3) -> @dependsOn(0) ReturnType
+func f(arg1: Type1, arg2: Type2, arg3: Type3) -> dependsOn(0) ReturnType
 ```
 
 ## Acknowledgements

From 40a78d95baba5d85647c1435c1a80ba4df3c7909 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Thu, 2 May 2024 19:22:02 -0700
Subject: [PATCH 17/59] Changed `StorageView` and `BufferReference` to `Span`
 to match the sibling proposal.

---
 proposals/NNNN-lifetime-dependency.md | 54 +++++++++++++--------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index e643918397..0631023d8a 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -12,14 +12,16 @@ We would like to propose extensions to Swift's function-declaration syntax that
 These would also be useable with methods that wish to declare a dependency on `self`.
 To reduce the burden of manually adding such annotations, we also propose inferring lifetime dependencies in certain common cases without requiring any additional annotations.
 
-This is a key requirement for the `StorageView` type (previously called `BufferView`) being discussed elsewhere, and is closely related to the proposal for `~Escapable` types.
+This is a key requirement for the `Span` type (previously called `BufferView`) being discussed elsewhere, and is closely related to the proposal for `~Escapable` types.
 
 **Edited** (Apr 12, 2024): Changed `@dependsOn` to `dependsOn` to match the current implementation.
 
+**Edited** (May 2, 2024): Changed `StorageView` and `BufferReference` to `Span` to match the sibling proposal.
+
 #### See Also
 
 * **TODO**: **** Forum thread discussing this proposal
-* [Pitch Thread for StorageView](https://forums.swift.org/t/pitch-safe-access-to-contiguous-storage/69888)
+* [Pitch Thread for Span](https://forums.swift.org/t/pitch-safe-access-to-contiguous-storage/69888)
 * [Forum discussion of BufferView language requirements](https://forums.swift.org/t/roadmap-language-support-for-bufferview)
 * [Proposed Vision document for BufferView language requirements (includes description of ~Escapable)](https://github.com/atrick/swift-evolution/blob/fd63292839808423a5062499f588f557000c5d15/visions/language-support-for-BufferView.md#non-escaping-bufferview) 
 
@@ -75,12 +77,10 @@ These types are not allowed to escape the local context except in very specific
 A separate proposal explains the general syntax and semantics of `Escapable` and `~Escapable`.
 
 By themselves, nonescapable types have severe constraints on usage.
-For example, consider a hypothetical `BufferReference` type that is similar to the standard library `UnsafeBufferPointer` or the `StorageView` type that is being proposed for inclusion in the standard library.
-It simply holds a pointer and size and can be used to access data stored in a contiguous block of memory.
-(We are not proposing this type; it is shown here merely for illustrative purposes.)
+For example, consider a hypothetical `Span` type that is similar type that is being proposed for inclusion in the standard library. It simply holds a pointer and size and can be used to access data stored in a contiguous block of memory. (We are not proposing this type; it is shown here merely for illustrative purposes.)
 
 ```swift
-struct BufferReference<T>: ~Escapable {
+struct Span<T>: ~Escapable {
   private var base: UnsafePointer<T>
   private var count: Int
 }
@@ -94,35 +94,35 @@ In the most common cases, these constraints can be inferred automatically.
 
 To make the semantics clearer, we’ll begin by describing how one can explicitly specify a lifetime constraint in cases where the default inference rules do not apply.
 
-Let’s consider adding support for our hypothetical `BufferReference` type to `Array`.
-Our proposal would allow you to declare an `array.bufferReference()` method as follows:
+Let’s consider adding support for our hypothetical `Span` type to `Array`.
+Our proposal would allow you to declare an `array.span()` method as follows:
 
 ```swift
 extension Array {
-  borrowing func bufferReference() -> dependsOn(self) BufferReference<Element> {
-    ... construct a BufferReference ...
+  borrowing func span() -> dependsOn(self) Span<Element> {
+    ... construct a Span ...
   }
 }
 ```
 
 The annotation `dependsOn(self)` here indicates that the returned value must not outlive the array that produced it.
 Conceptually, it is a continuation of the function's borrowing access:
-the array is being borrowed by the function while the function executes and then continues to be borrowed by the `BufferReference` for as long as the return value exists.
+the array is being borrowed by the function while the function executes and then continues to be borrowed by the `Span` for as long as the return value exists.
 Specifically, the `dependsOn(self)` annotation in this example informs the compiler that:
 
-* The array must not be destroyed until after the `BufferReference<Element>` is destroyed.
+* The array must not be destroyed until after the `Span<Element>` is destroyed.
   This ensures that use-after-free cannot occur.
-* The array must not be mutated while the  `BufferReference<Element>` value exists.
+* The array must not be mutated while the  `Span<Element>` value exists.
   This follows the usual Swift exclusivity rules for a borrowing access.
 
 #### Scoped Lifetime Dependency
 
-Let’s consider another hypothetical type: a `MutatingBufferReference<T>` type that could provide indirect mutating access to a block of memory.
+Let’s consider another hypothetical type: a `MutatingSpan<T>` type that could provide indirect mutating access to a block of memory.
 Here's one way such a value might be produced:
 
 ```swift
-func mutatingBufferReference(to: inout Array, count: Int) -> dependsOn(to) MutatingBufferReference<Element> {
-  ... construct a MutatingBufferReference ...
+func mutatingSpan(to: inout Array, count: Int) -> dependsOn(to) MutatingSpan<Element> {
+  ... construct a MutatingSpan ...
 }
 ```
 
@@ -131,21 +131,21 @@ The `dependsOn(to)` annotation indicates that the returned value depends on the
 Because `count` is not mentioned in the lifetime dependency, that argument does not participate.
 Similar to the previous example:
 
-* The array will not be destroyed until after the `MutatingBufferReference<Element>` is destroyed.
+* The array will not be destroyed until after the `MutatingSpan<Element>` is destroyed.
 * No other read or write access to the array will be allowed for as long as the returned value exists.
 
 In both this and the previous case, the lifetime of the return value is "scoped" to the lifetime of the original value.
 Because lifetime dependencies can only be attached to nonescapable values, types that contain pointers will generally need to be nonescapable in order to provide safe semantics.
-As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as an Array or similar container) is providing a nonescapable value (such as the `BufferReference` or `MutatingBufferReference` in these examples).
+As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as an Array or similar container) is providing a nonescapable value (such as the `Span` or `MutatingSpan` in these examples).
 
 #### Copied Lifetime Dependency
 
 The case where a nonescapable value is used to produce another nonescapable value is somewhat different.
-Here's a typical example that constructs a new `BufferReference` from an existing one:
+Here's a typical example that constructs a new `Span` from an existing one:
 ```swift
-struct BufferReference<T>: ~Escapable {
+struct Span<T>: ~Escapable {
   ...
-  consuming func drop(_: Int) -> dependsOn(self) BufferReference<T> { ... }
+  consuming func drop(_: Int) -> dependsOn(self) Span<T> { ... }
   ...
 }
 ```
@@ -155,12 +155,12 @@ Recall that nonescapable values such as these represent values that are already
 
 For a `consuming` method, the return value cannot have a scoped lifetime dependency on the original value, since the original value no longer exists when the method returns.
 Instead, the return value must "copy" the lifetime dependency from the original:
-If the original `BufferReference` was borrowing some array, the new `BufferReference` will continue to borrow the same array.
+If the original `Span` was borrowing some array, the new `Span` will continue to borrow the same array.
 
 This supports coding patterns such as this:
 ```swift
 let a: Array<Int>
-let ref1 = a.bufferReference() // ref1 cannot outlive a
+let ref1 = a.span() // ref1 cannot outlive a
 let ref2 = ref1.drop(4) // ref2 also cannot outlive a
 ```
 
@@ -413,21 +413,21 @@ We propose above putting the annotation on the return value, which we believe ma
 It would also be possible to put an annotation on the parameters instead:
 
 ```swift
-func f(@resultDependsOn arg1: Array<Int>) -> BufferReference<Int>
+func f(@resultDependsOn arg1: Array<Int>) -> Span<Int>
 ```
 
 Depending on the exact language in use, it could also be more natural to put the annotation after the return value.
 However, we worry that this hides this critical information in cases where the return type is longer or more complex.
 
 ```swift
-func f(arg1: Array<Int>) -> BufferReference<Int> dependsOn(arg1)
+func f(arg1: Array<Int>) -> Span<Int> dependsOn(arg1)
 ```
 
 ### Different spellings
 
 An earlier version of this proposal advocated using the existing `borrow`/`mutate`/`consume`/`copy` keywords to specify a particular lifetime dependency semantic:
 ```swift
-func f(arg1: borrow Array<Int>) -> borrow(arg1) BufferReference<Int>
+func f(arg1: borrow Array<Int>) -> borrow(arg1) Span<Int>
 ```
 This was changed after we realized that there was in practice almost always a single viable semantic for any given situation, so the additional refinement seemed unnecessary.
 
@@ -483,7 +483,7 @@ We expect to address this in the near future in a separate proposal.
 It should be possible to return containers with collections of lifetime-constrained elements.
 For example, a container may want to return a partition of its contents:
 ```swift
-borrowing func chunks(n: Int) -> dependsOn(self) SomeList<dependsOn(self) StorageView<UInt8>>
+borrowing func chunks(n: Int) -> dependsOn(self) SomeList<dependsOn(self) Span<UInt8>>
 ```
 We're actively looking into ways to support these more involved cases and expect to address this in a future proposal.
 

From 25e43554738f3da3d3feab85c17960cdc392922d Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Sat, 4 May 2024 07:54:10 -0700
Subject: [PATCH 18/59] Add a link to the forum discussion.

---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 0631023d8a..b83cd2e491 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -20,7 +20,7 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 
 #### See Also
 
-* **TODO**: **** Forum thread discussing this proposal
+* [Forum discussion of Non-Escapable Types and Lifetime Dependency](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency)
 * [Pitch Thread for Span](https://forums.swift.org/t/pitch-safe-access-to-contiguous-storage/69888)
 * [Forum discussion of BufferView language requirements](https://forums.swift.org/t/roadmap-language-support-for-bufferview)
 * [Proposed Vision document for BufferView language requirements (includes description of ~Escapable)](https://github.com/atrick/swift-evolution/blob/fd63292839808423a5062499f588f557000c5d15/visions/language-support-for-BufferView.md#non-escaping-bufferview) 

From af162efc2135a03fd35b4eeed1d18e81d68b1f1d Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 28 May 2024 10:41:03 -0700
Subject: [PATCH 19/59] Additions to Proposed solutions

- Dependent parameters
- Dependent properties
- Conditional dependencies
- Immortal lifetimes
- Depending on immutable global variables
- Depending on an escapable `BitwiseCopyable` value
- Depending on an escapable `BitwiseCopyable` value
---
 proposals/NNNN-lifetime-dependency.md | 198 ++++++++++++++++++++++++++
 1 file changed, 198 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index b83cd2e491..1a682567b4 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -275,6 +275,204 @@ func g(... arg1: borrowing Type1, arg2: NEType, ...) -> NEType
 
 We expect these implicit inferences to cover most cases, with the explicit form only occasionally being necessary in practice.
 
+### Dependent parameters
+
+Normally, lifetime dependence is required when a nonescapable function result depends on an argument to that function. In some rare cases, however, a nonescapable function parameter may depend on another argument to that function. Consider a function with an `inout` parameter. The function body may reassign that parameter to a value that depends on another parameter. This is similar in principle to a result dependence.
+
+```swift
+func mayReassign(span: dependsOn(a) inout [Int], to a: [Int]) {
+  span = a.span()
+}
+```
+
+A `selfDependsOn` keyword is required to indicate that a method's implicit `self` depends on another parameter.
+
+```swift
+extension Span {
+  mutating selfDependsOn(other) func reassign(other: Span<T>) {
+    self = other // âś… OK: 'self' depends on 'other'
+  }
+}
+```
+
+We've discussed how a nonescapable result must be destroyed before the source of its lifetime dependence. Similarly, a dependent argument must be destroyed before an argument that it depends on. The difference is that the dependent argument may already have a lifetime dependence when it enters the function. The new function argument dependence is additive, because the call does not guarantee reassignment. Instead, passing the 'inout' argument is like a conditional reassignment. After the function call, the dependent argument carries both lifetime dependencies.
+
+```swift
+  let a1: Array<Int> = ...
+  var span = a1.span()
+  let a2: Array<Int> = ...
+  mayReassign(span: &span, to: a2)
+  // 'span' now depends on both 'a1' and 'a2'.
+```
+
+### Dependent properties
+
+Structural composition is an important use case for nonescapable types. Getting or setting a nonescapable property requires lifetime dependence, just like a function result or an 'inout' parameter. There's no need for explicit annotation in these cases, because only one dependence is possible. A getter returns a value that depends on `self`. A setter replaces the current dependence from `self` with a dependence on `newValue`.
+
+```swift
+struct Container<Element>: ~Escapable {
+  var element: Element {
+    /* dependsOn(self) */ get { ... }
+    /* selfDependsOn(newValue) */ set { ... }
+  }
+
+  init(element: Element) /* -> dependsOn(element) Self */ {...}
+}
+```
+
+### Conditional dependencies
+
+Conditionally nonescapable types can contain nonescapable elements:
+
+```swift
+    struct Container<Element>: ~Escapable {
+      var element: /* dependsOn(self) */ Element
+
+      init(element: Element) -> dependsOn(element) Self {...}
+
+      func getElement() -> dependsOn(self) Element { element }
+    }
+
+    extension Container<E> { // OK: conforms to Escapable.
+      // Escapable context...
+    }
+```
+
+Here, `Container` becomes nonescapable only when its element type is nonescapable. When `Container` is nonescapable, it inherits the lifetime of its single element value from the initializer and propagates that lifetime to all uses of its `element` property or the `getElement()` function.
+
+In some contexts, however, `Container` and `Element` both conform to `Escapable`. In those contexts, any `dependsOn` in `Container`'s interface is ignored, whether explicitly annotated or implied. So, when `Container`'s element conforms to `Escapable`, the `-> dependsOn(element) Self` annotation in its initializer is ignored, and the `-> dependsOn(self) Element` in `getElement()` is ignored.
+
+### Immortal lifetimes
+
+In some cases, a nonescapable value must be constructed without any object that can stand in as the source of a dependence. Consider extending the standard library `Optional` or `Result` types to be conditionally escapable:
+
+```swift
+enum Optional<Wrapped: ~Escapable>: ~Escapable {
+  case none, some(Wrapped)
+}
+
+extension Optional: Escapable where Wrapped: Escapable {}
+
+enum Result<Success: ~Escapable, Failure: Error>: ~Escapable {
+  case failure(Failure), success(Success)
+}
+
+extension Result: Escapable where Success: Escapable {}
+```
+
+When constructing an `Optional<NotEscapable>.none` or `Result<NotEscapable>.failure(error)` case, there's no lifetime to assign to the constructed value in isolation, and it wouldn't necessarily need one for safety purposes, because the given instance of the value doesn't store any state with a lifetime dependency. Instead, the initializer for cases like this can be annotated with `dependsOn(immortal)`:
+
+```swift
+extension Optional {
+  init(nilLiteral: ()) dependsOn(immortal) {
+    self = .none
+  }
+}
+```
+
+Once the escapable instance is constructed, it is limited in scope to the caller's function body since the caller only sees the static nonescapable type. If a dynamically escapable value needs to be returned further up the stack, that can be done by chaining multiple `dependsOn(immortal)` functions.
+
+#### Depending on immutable global variables
+
+Another place where immortal lifetimes might come up is with dependencies on global variables. When a value has a scoped dependency on a global let constant, that constant lives for the duration of the process and is effectively perpetually borrowed, so one could say that values dependent on such a constant have an effectively infinite lifetime as well. This will allow returning a value that depends on a global by declaring the function's return type with `dependsOn(immortal)`:
+
+```swift
+let staticBuffer = ...
+
+func getStaticallyAllocated() -> dependsOn(immortal) BufferReference {
+  staticBuffer.bufferReference()
+}
+```
+
+### Depending on an escapable `BitwiseCopyable` value
+
+The source of a lifetime depenence may be an escapable `BitwiseCopyable` value. This is useful in the implementation of data types that internally use `UnsafePointer`:
+
+```swift
+struct Span<T>: ~Escapable {
+  ...
+  // The caller must ensure that `unsafeBaseAddress` is valid over all uses of the result.
+  init(unsafeBaseAddress: UnsafePointer<T>, count: Int) dependsOn(unsafeBaseAddress) { ... }
+  ...
+}
+```
+
+By convention, when the source of a dependence is escapable and `BitwiseCopyable`, it should have an "unsafe" label, such as `unsafeBaseAddress` above. This communicates to anyone who calls the function, that they are reponsibile for ensuring that the value that the result depends on is valid over all uses of the result. The compiler can't guarantee safety because `BitwiseCopyable` types do not have a formal point at which the value is destroyed. Specifically, for `UnsafePointer`, the compiler does not know which object owns the pointed-to storage.
+
+```swift
+var span: Span<T>?
+let buffer: UnsafeBufferPointer<T>
+do {
+  let storage = Storage(...)
+  buffer = storage.buffer
+  span = Span(unsafeBaseAddress: buffer.baseAddress!, count: buffer.count)
+  // 🔥 'storage' may be destroyed
+}
+decode(span!) // 👿 Undefined behavior: dangling pointer
+```
+
+Normally, `UnsafePointer` lifetime guarantees naturally fall out of closure-taking APIs that use `withExtendedLifetime`:
+
+```swift
+extension Storage {
+  public func withUnsafeBufferPointer<R>(
+    _ body: (UnsafeBufferPointer<Element>) throws -> R
+  ) rethrows -> R {
+    withExtendedLifetime (self) { ... }
+  }
+}
+
+let storage = Storage(...)
+storage.withUnsafeBufferPointer { buffer in
+  let span = Span(unsafeBaseAddress: buffer.baseAddress!, count: buffer.count)
+  decode(span!) // âś… Safe: 'buffer' is always valid within the closure.
+}
+```
+
+### Standard library extensions
+
+#### Conditionally nonescapable types
+
+The following standard library types will become conditionally nonescapable: `Optional`, `ExpressibleByNilLiteral`, and `Result`.
+
+`MemoryLayout` will suppress the escapable constraint on its generic parameter.
+
+#### `unsafeLifetime` helper functions
+
+The following two helper functions will be added for implementing low-level data types:
+
+```swift
+/// Replace the current lifetime dependency of `dependent` with a new copied lifetime dependency on `source`.
+///
+/// Precondition: `dependent` has an independent copy of the dependent state captured by `source`.
+func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
+  dependent: consuming T, dependsOn source: borrowing U)
+  -> dependsOn(source) T { ... }
+
+/// Replace the current lifetime dependency of `dependent` with a new scoped lifetime dependency on `source`.
+///
+/// Precondition: `dependent` depends on state that remains valid until either:
+/// (a) `source` is either destroyed if it is immutable,
+/// or (b) exclusive to `source` access ends if it is a mutable variable.
+func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
+  dependent: consuming T, scoped source: borrowing U)
+  -> dependsOn(scoped source) T {...}
+```
+
+These are useful for nonescapable data types that are internally represented using escapable types such as `UnsafePointer`. For example, some methods on `Span` will need to derive a new `Span` object that copies the lifetime dependence of `self`:
+
+```swift
+extension Span {
+  consuming func dropFirst() -> Span<T> {
+    let local = Span(base: self.base + 1, count: self.count - 1)
+    // 'local' can persist after 'self' is destroyed.
+    return unsafeLifetime(dependent: local, dependsOn: self)
+  }
+}
+```
+
+Since `self.base` is an escapable value, it does not propagate the lifetime dependence of its container. Without the call to `unsafeLifetime`, `local` would be limited to the local scope of the value retrieved from `self.base`, and could not be returned from the method. In this example, `unsafeLifetime` communicates that all of the dependent state from `self` has been *copied* into `local`, and, therefore, `local` can persist after `self` is destroyed.
+
 ## Detailed design
 
 ### Relation to ~Escapable

From adfe8a032e11d2f1c2de39d797ec12593429168c Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 28 May 2024 10:45:07 -0700
Subject: [PATCH 20/59] Dependency semantics by example

---
 proposals/NNNN-lifetime-dependency.md | 130 ++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 1a682567b4..a62fc57d64 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -589,6 +589,136 @@ In this case, the compiler will infer a dependency on the unique argument identi
 **In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
 If a function, method, or initializer has a nonescapable return value, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
 
+
+### Dependency semantics by example
+
+This section illustrates the semantics of lifetime dependence one example at a time for each interesting variation. The following helper functions will be useful: `Array.span()` creates a scoped dependence to a nonescapable `Span` result, `copySpan()` creates a copied dependence to a `Span` result, and `parse` uses a `Span`.
+
+```swift
+extension Array {
+  // The returned span depends on the scope of Self.
+  borrowing func span() -> /* dependsOn(scoped self) */ Span<Element> { ... }
+}
+
+// The returned span copies dependencies from 'arg'.
+func copySpan<T>(_ arg: Span<T>) -> /* dependsOn(arg) */ Span<T> { arg }
+
+func parse(_ span: Span<Int>) { ... }
+```
+
+#### Scoped dependence on an immutable variable
+
+```swift
+let a: Array<Int> = ...
+let span: Span<Int>
+do {
+  let a2 = a
+  span = a2.span()
+}
+parse(span) // 🛑 Error: 'span' escapes the scope of 'a2'
+```
+
+The call to `span()` creates a scoped dependence on `a2`. A scoped dependence is determined by the lifetime of the variable, not the lifetime of the value assigned to that variable. So the lifetime of `span` cannot extend into the larger lifetime of `a`.
+
+#### Copied dependence on an immutable variable
+
+Let's contrast scoped dependence shown above with copied dependence on a variable. In this case, the value may outlive the variable it is copied from, as long as it is destroyed before the root of its inherited dependence goes out of scope. A chain of copied dependencies is always rooted in a scoped dependence.
+
+An assignment that copies or moves a nonescapable value from one variable into another **copies** any lifetime dependence from the source value to the destination value. Thus, variable assignment has the same lifetime copy semantics as passing an argument using a `dependsOn()` annotation *without* a `scoped` keyword. So, the statement `let temp = span` has identical semantics to `let temp = copySpan(span)`.
+
+```swift
+let a: Array<Int> = arg
+let final: Span<Int>
+do {
+  let span = a.span()
+  let temp = span
+  final = copySpan(temp)
+}
+parse(final) // âś… Safe: still within lifetime of 'a'
+```
+
+Although the result of `copySpan` depends on `temp`, the result of the copy may be used outside of the `temp`'s lexical scope. Following the source of each copied dependence, up through the call chain if needed, eventually leads to the scoped dependence root. Here, `final` is the end of a lifetime dependence chain rooted at a scoped dependence on `a`:
+`a -> span -> temp -> {copySpan argument} -> final`. `final` is therefore valid within the scope of `a` even if the intermediate copies have been destroyed.
+
+#### Copied dependence on a mutable value
+
+First, let's add a mutable method to `Span`:
+
+```swift
+extension Span {
+  mutating func droppingPrefix(length: Int) -> /* dependsOn(self) */ Span<T> {
+    let result = Span(base: base, count: length)
+    self.base += length
+    self.count -= length
+    return result
+  }
+}
+```
+
+A dependence may be copied from a mutable ('inout') variable. In that case, the dependence is inherited from whatever value the mutable variable holds when it is accessed.
+
+```swift
+let a: Array<Int> = ...
+var prefix: Span<Int>
+do {
+  var temp = a.span()
+  prefix = temp.droppingPrefix(length: 1) // access 'temp' as 'inout'
+  // 'prefix' depends on 'a', not 'temp'
+}
+parse(prefix) // âś… Safe: still within lifetime of 'a'
+```
+
+#### Scoped dependence on 'inout' access
+
+Now, let's return to scoped dependence, this time on a mutable variable. This is where exclusivity guarantees come into play. A scoped depenendence extends an access of the mutable variable across all uses of the dependent value. If the variable mutates again before the last use of the dependent, then it is an exclusivity violation.
+
+```swift
+let a: Array<Int> = ...
+a[i] = ...
+let span = a1.span()
+parse(span) // âś… Safe: still within 'span's access on 'a'
+a[i] = ...
+parse(span) // 🛑 Error: simultaneous access of 'a'
+```
+
+Here, `a1.span()` initiates a 'read' access on `a1`. The first call to `parse(span)` safely extends that read access. The read cannot extend to the second call because a mutation of `a1` occurs before it.
+
+#### Dependence reassignment
+
+We've described how a mutable variable can be the source of a lifetime dependence. Now let's look at nonescapable mutable variables. Being nonescapable means they depend on another lifetime. Being mutable means that dependence may change during reassignment. Reassigning a nonescapable 'inout' sets its lifetime dependence from that point on, up to either the end of the variable's lifetime or its next subsequent reassignment.
+
+```swift
+func reassign(_ span: inout Span<Int>) {
+  let a: Array<Int> = ...
+  span = a.span() // 🛑 Error: 'span' escapes the scope of 'a'
+}
+```
+
+#### Reassignment with argument dependence
+
+If a function takes a nonescapable 'inout' argument, it may only reassign that argument if it is marked dependent on another function argument that provies the source of the dependence.
+
+```swift
+func reassignWithArgDependence(_ span: dependsOn(arg) inout [Int], _ arg: [Int]) {
+  span = arg.span() //  âś… OK: 'span' already depends on 'arg' in the caller's scope.
+}
+```
+
+#### Conditional reassignment creates conjoined dependence
+
+'inout' argument dependence behaves like a conditional reassignment. After the call, the variable passed to the 'inout' argument has both its original dependence along with a new dependence on the argument that is the source of the argument dependence.
+
+```swift
+let a1: Array<Int> = arg
+do {
+  let a2: Array<Int> = arg
+  var span = a1.span()
+  testReassignArgDependence(&span, a2) // creates a conjoined dependence
+  parse(span) // âś… OK: within the lifetime of 'a1' & 'a2'
+}
+parse(span) // 🛑 Error: 'span' escapes the scope of 'a2'
+```
+
 ## Source compatibility
 
 Everything discussed here is additive to the existing Swift grammar and type system.

From 3b6f859c5d7651da35bd40250f9f9910a65a7fe9 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 28 May 2024 10:45:43 -0700
Subject: [PATCH 21/59] Cleanup Future directions

Remove Lifetime Dependencies for Computed Properties

Remove Lifetime Dependencies between arguments
---
 proposals/NNNN-lifetime-dependency.md | 36 +++------------------------
 1 file changed, 4 insertions(+), 32 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index a62fc57d64..3684c0e9f7 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -761,26 +761,7 @@ This was changed after we realized that there was in practice almost always a si
 
 ## Future Directions
 
-#### Lifetime Dependencies for Computed Properties
-
-It would be useful to allow lifetime dependencies between `self` and the value returned by a computed property.
-There is some ambiguity here, since resilience hides the distinction between a computed and stored property.
-In particular, the resilience concern might prevent us from inferring lifetime dependencies for properties across module boundaries.
-The notation for an explicit lifetime dependency on a property might look like the following:
-
-```swift
-struct Container {
-  var view: dependsOn(self) ReturnType { get }
-}
-
-struct Type1: ~Escapable {
-  var childView: dependsOn(self) Type1 { get }
-}
-```
-
-We expect that the lifetime notation would be mandatory for any property that provided a `~Escapable` value.
-
-#### Lifetime Dependencies for Escapable Types
+### Lifetime Dependencies for Escapable Types
 
 This proposal has deliberately limited the application of lifetime dependencies to return types that are nonescapable.
 This simplifies the model by identifying nonescapable types as exactly those types that can carry such dependencies.
@@ -788,16 +769,7 @@ It also helps simplify the enforcement of lifetime constraints by guaranteeing t
 Most importantly, this restriction helps ensure that the new semantics (especially lifetime dependency inference) cannot accidentally break existing code.
 We expect that in the future, additional investigation can reveal a way to relax this restriction.
 
-#### Lifetime Dependencies between arguments
-
-A caller may need assurance that a callee will honor a lifetime dependency between two arguments.
-For example, if a function is going to destroy a container and a reference to that container in the process of computing some result,
-it needs to guarantee that the reference is destroyed before the container:
-```swift
-func f(container: consuming ContainerType, ref: dependsOn(container) consuming RefType) -> ResultType
-```
-
-#### Lifetime Dependencies for Tuples
+### Lifetime Dependencies for Tuples
 
 It should be possible to return a tuple where one part has a lifetime dependency.
 For example:
@@ -806,7 +778,7 @@ func f(a: consume A, b: B) -> (consume(a) C, B)
 ```
 We expect to address this in the near future in a separate proposal.
 
-#### Lifetime Dependencies for containers and their elements
+### Lifetime Dependencies for containers and their elements
 
 It should be possible to return containers with collections of lifetime-constrained elements.
 For example, a container may want to return a partition of its contents:
@@ -815,7 +787,7 @@ borrowing func chunks(n: Int) -> dependsOn(self) SomeList<dependsOn(self) Span<U
 ```
 We're actively looking into ways to support these more involved cases and expect to address this in a future proposal.
 
-#### Parameter index for lifetime dependencies
+### Parameter index for lifetime dependencies
 
 Internally, the implementation records dependencies based on the parameter index.
 This could be exposed as an alternate spelling if there were sufficient demand.

From 2fd52e153c8e5037fa5802082adf21706066163a Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 28 May 2024 10:47:04 -0700
Subject: [PATCH 22/59] Additions to Future directions

- Value component lifetime
- Abstract lifetime components
- Protocol lifetime requirements
- Structural lifetime dependencies
---
 proposals/NNNN-lifetime-dependency.md | 182 ++++++++++++++++++++++++++
 1 file changed, 182 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 3684c0e9f7..f5f01c348c 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -796,6 +796,188 @@ This could be exposed as an alternate spelling if there were sufficient demand.
 func f(arg1: Type1, arg2: Type2, arg3: Type3) -> dependsOn(0) ReturnType
 ```
 
+### Value component lifetime
+
+In the current design, aggregating multiple values merges their scopes.
+
+```swift
+struct Container<Element>: ~Escapable {
+  var a: /*dependsOn(self)*/ Element
+  var b: /*dependsOn(self)*/ Element
+
+  init(a: Element, b: Element) -> dependsOn(a, b) Self {...}
+}
+```
+
+This can have the effect of narrowing the lifetime scope of some components:
+
+```swift
+var a = ...
+{
+  let b = ...
+  let c = Container<Element>(a: a, b: b)
+  a = c.a // 🛑 Error: `a` outlives `c.a`, which is constrained by the lifetime of `b`
+}
+```
+
+In the future, the lifetimes of multiple values can be represented independently by attaching a `@lifetime` attribute to a stored property and referring to that property's name inside `dependsOn` annotations:
+
+```swift
+struct Container<Element>: ~Escapable {
+  @lifetime
+  var a: /*dependsOn(self.a)*/ Element
+  @lifetime
+  var b: /*dependsOn(self.b)*/ Element
+
+  init(a: Element, b: Element) -> dependsOn(a -> .a, b -> .b) Self {...}
+}
+```
+
+The nesting level of a component is the inverse of the nesting level of its lifetime. `a` and `b` are nested components of `Container`, but the lifetime of a `Container` instance is nested within both lifetimes of `a` and `b`.
+
+### Abstract lifetime components
+
+Lifetime dependence is not always neatly tied to stored properties. Say that our `Container` now holds multiple elements within its own storage. We can use a top-level `@lifetime` annotation to name an abstract lifetime for all the elements:
+
+```swift
+@lifetime(elements)
+struct Container<Element>: ~Escapable {
+  var storage: UnsafeMutablePointer<Element>
+
+  init(element: Element) -> dependsOn(element -> .elements) Self {...}
+
+  subscript(position: Int) -> dependsOn(self.elements) Element
+}
+```
+
+Note that a subscript setter reverses the dependence: `dependsOn(newValue -> .elements)`.
+
+As before, when `Container` held a single element, it can temporarily take ownership of an element without narrowing its lifetime:
+
+```swift
+var c1: Container<Element>
+{
+  let c2 = Container<Element>(element: c1[i])
+  c1[i] = c2[i] // OK: c2[i] can outlive c2
+}
+```
+
+Now let's consider a `View` type, similar to `Span`, that provides access to a borrowed container's elements. The lifetime of the view depends on the container's storage. Therefore, the view depends on a *borrow* of the container. The container's elements, however, no longer depend on the container's storage once they have been copied. This can be expressed by giving the view an abstract lifetime for its elements, separate from the view's own lifetime:
+
+```swift
+@lifetime(elements)
+struct View<Element>: ~Escapable {
+  var storage: UnsafePointer<Element>
+
+  init(container: Container)
+    -> dependsOn(container.elements -> .elements) // Copy the lifetime associated with container.elements
+    Self {...}
+
+  subscript(position: Int) -> dependsOn(self.elements) Element
+}
+
+@lifetime(elements)
+struct MutableView<Element>: ~Escapable, ~Copyable {
+  var storage: UnsafeMutablePointer<Element>
+  //...
+}
+
+extension Container {
+  // Require a borrow scope in the caller that borrows the container
+  var view: dependsOn(borrow self) View<Element> { get {...} }
+
+  var mutableView: dependsOn(borrow self) MutableView<Element> { mutating get {...} }
+}
+```
+
+Now an element can be copied out of a view `v2` and assigned to another view `v1` whose lifetime exceeds the borrow scope that constrains the lifetime of `v2`.
+
+```swift
+var c1: Container<Element>
+let v1 = c1.mutableView
+{
+  let v2 = c1.view // borrow scope for `v2`
+  v1[i] = v2[i] // OK: v2[i] can outlive v2
+}
+```
+
+To see this more abstractly, rather than directly assigning, `v1[i] = v2[i]`, we can use a generic interface:
+
+```swift
+func transfer(from: Element, to: dependsOn(from) inout Element) {
+  to = from
+}
+
+var c1: Container<Element>
+let v1 = c1.mutableView
+{
+  let v2 = c1.view // borrow scope for `v2`
+  transfer(from: v2[i], to: &v1[i]) // OK: v2[i] can outlive v2
+}
+```
+
+### Protocol lifetime requirements
+
+Value lifetimes are limited because they provide no way to refer to a lifetime without refering to a concrete type that the lifetime is associated with. To support generic interfaces, protocols need to refer to any lifetime requirements that can appear in interface.
+
+Imagine that we want to access view through a protocol. To support returning elements that outlive the view, we need to require an `elements` lifetime requirement:
+
+```swift
+@lifetime(elements)
+protocol ViewProtocol {
+  subscript(position: Int) -> dependsOn(self.elements) Element
+}
+```
+
+Let's return to View's initializer;
+
+```swift
+@lifetime(elements)
+struct View<Element>: ~Escapable {
+  init(container: borrowing Container) ->
+    // Copy the lifetime assoicate with container.elements
+    dependsOn(container.elements -> .elements)
+    Self {...}
+}
+```
+
+This is not a useful initializer, because `View` should not be specific to a concrete `Container` type. Instead, we want `View` to be generic over any container that provides `elements` that can be copied out of the container's storage:
+
+```swift
+@lifetime(elements)
+protocol ElementStorage: ~Escapable {}
+
+@lifetime(elements)
+struct View<Element>: ~Escapable {
+  init(storage: ElementStorage) ->
+    // Copy the lifetime assoicate with storage.elements
+    dependsOn(storage.elements -> .elements)
+    Self {...}
+}
+```
+
+### Structural lifetime dependencies
+
+A scoped dependence normally cannot escape the lexical scope of its source variable. It may, however, be convenient to escape the source of that dependence along with any values that dependent on its lifetime. This could be done by moving the ownership of the source into a structure that preserves any dependence relationships. A function that returns a nonescapable type cannot currently depend on the scope of a consuming parameter. But we could lift that restriction provided that the consumed argument is moved into the return value, and that the return type preserves any dependence on that value:
+
+```swift
+struct OwnedSpan<T>: ~Copyable & ~Escapable{
+  let owner: any ~Copyable
+  let span: dependsOn(scope owner) Span<T>
+
+  init(owner: consuming any ~Copyable, span: dependsOn(scope owner) Span<T>) -> dependsOn(scoped owner) Self {
+    self.owner = owner
+    self.span = span
+  }
+}
+
+func arrayToOwnedSpan<T>(a: consuming [T]) -> OwnedSpan<T> {
+  OwnedSpan(owner: a, span: a.span())
+}
+```
+
+`arrayToOwnedSpan` creates a span with a scoped dependence on an array, then moves both the array and the span into an `OwnedSpan`, which can be returned from the function. This converts the original lexically scoped dependence into a structural dependence.
+
 ## Acknowledgements
 
 Dima Galimzianov provided several examples for Future Directions.

From 1c5a02ea9c63d7c393c257eec3c8bc3c32738ebc Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 28 May 2024 10:48:42 -0700
Subject: [PATCH 23/59] Grammar updates

---
 proposals/NNNN-lifetime-dependency.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index f5f01c348c..7714221e46 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -504,6 +504,12 @@ The compiler must issue a diagnostic if any of the above cannot be satisfied.
 
 ### Grammar
 
+
+TODO:
+
+* dependent parameters
+* 'immortal' keyword
+
 This new syntax adds an optional lifetime modifier just before the return type.
 This modifies *function-result* in the Swift grammar as follows:
 

From def2c821993c1184e1cbf3d62d17795b78d707ac Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 28 May 2024 22:56:24 -0700
Subject: [PATCH 24/59] Update and cleanup the grammar.

Add dependent parameters, immortal dependencies, and 'selfDependsOn'.
---
 proposals/NNNN-lifetime-dependency.md | 29 +++++++++++++++------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 7714221e46..0407bc22bc 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -504,29 +504,32 @@ The compiler must issue a diagnostic if any of the above cannot be satisfied.
 
 ### Grammar
 
+This new syntax adds an optional `dependsOn(...)` lifetime modifier just before the return type and parameter types. This modifies *function-result* in the Swift grammar as follows:
 
-TODO:
-
-* dependent parameters
-* 'immortal' keyword
-
-This new syntax adds an optional lifetime modifier just before the return type.
-This modifies *function-result* in the Swift grammar as follows:
-
->
 > *function-signature* → *parameter-clause* **`async`***?* **`throws`***?* *function-result**?* \
 > *function-signature* → *parameter-clause* **`async`***?* **`rethrows`** *function-result**?* \
 > *function-result* → **`->`** *attributes?* *lifetime-modifiers?* *type* \
-> *lifetime-modifiers* → **`->`** *lifetime-modifier* *lifetime-modifiers?* \
-> *lifetime-modifier* → **`->`** **`dependsOn`** **`(`** *lifetime-dependent* **`)`** \
-> *lifetime-dependent* → **`->`** **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name*
+> *lifetime-modifiers* → *lifetime-modifier* *lifetime-modifiers?* \
+> *lifetime-modifier* → **`dependsOn`** **`(`** *lifetime-dependent-list* **`)`** \
+> *lifetime-dependence-list* → *lifetime-dependent* | *lifetime-dependence-source* **`,`** *lifetime-dependent-list*
+> *lifetime-dependence-source* → **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name* | **`immortal`**
+>
+> *parameter-type-annotation* → : *attributes?* *lifetime-modifiers?* *parameter-modifier*? *type*
+>
+
+The new syntax also adds an optional `selfDependsOn(...)` lifetime modifier before function declarations. This extends *declaration-modifier* as follows:
+
+>
+> *declaration-modifier* → *self-lifetime-modifier* \
+> *self-lifetime-modifier* → **`selfDependsOn`** **`(`** *lifetime-dependent-list* **`)`**
 >
 
 The *lifetime-dependent* argument to the lifetime modifier is one of the following:
 
 * *local-parameter-name*: the local name of one of the function parameters, or
 * the token **`self`**, or
-* either of the above preceded by the **`scoped`** keyword
+* either of the above preceded by the **`scoped`** keyword, or
+* the token **`immortal`**
 
 This modifier creates a lifetime dependency with the return value used as the dependent value.
 The return value must be nonescapable.

From 992b2fe3b2b6e56190a7852947f2ed57ddb3c2d2 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Wed, 5 Jun 2024 13:25:32 -0700
Subject: [PATCH 25/59] Add a change log entry.

---
 proposals/NNNN-lifetime-dependency.md | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 0407bc22bc..8be68fc68d 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -18,6 +18,23 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 
 **Edited** (May 2, 2024): Changed `StorageView` and `BufferReference` to `Span` to match the sibling proposal.
 
+**Edited** (May 30, 2024): Added the following new sections:
+
+- Dependent parameters
+- Dependent properties
+- Conditional dependencies
+- Immortal lifetimes
+- Depending on immutable global variables
+- Depending on an escapable BitwiseCopyable value
+- Standard library extensions
+- unsafeLifetime helper functions
+- Dependency semantics by example
+- Future directions
+  - Value component lifetime
+  - Abstract lifetime components
+  - Protocol lifetime requirements
+  - Structural lifetime dependencies
+
 #### See Also
 
 * [Forum discussion of Non-Escapable Types and Lifetime Dependency](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency)

From aed8750f44f3e36119676c9f0ca8e353050cb9a1 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Fri, 7 Jun 2024 05:10:55 -0700
Subject: [PATCH 26/59] Syntax update: dependsOn(self).

---
 proposals/NNNN-lifetime-dependency.md | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 8be68fc68d..dd1af7badf 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -302,11 +302,11 @@ func mayReassign(span: dependsOn(a) inout [Int], to a: [Int]) {
 }
 ```
 
-A `selfDependsOn` keyword is required to indicate that a method's implicit `self` depends on another parameter.
+The `dependsOn(self:)` keyword is required to indicate that a method's implicit `self` depends on another parameter.
 
 ```swift
 extension Span {
-  mutating selfDependsOn(other) func reassign(other: Span<T>) {
+  mutating dependsOn(self: other) func reassign(other: Span<T>) {
     self = other // âś… OK: 'self' depends on 'other'
   }
 }
@@ -329,8 +329,8 @@ Structural composition is an important use case for nonescapable types. Getting
 ```swift
 struct Container<Element>: ~Escapable {
   var element: Element {
-    /* dependsOn(self) */ get { ... }
-    /* selfDependsOn(newValue) */ set { ... }
+    get /* dependsOn(self) */ { ... }
+    /* dependsOn(self: newValue) */ set { ... }
   }
 
   init(element: Element) /* -> dependsOn(element) Self */ {...}
@@ -534,11 +534,10 @@ This new syntax adds an optional `dependsOn(...)` lifetime modifier just before
 > *parameter-type-annotation* → : *attributes?* *lifetime-modifiers?* *parameter-modifier*? *type*
 >
 
-The new syntax also adds an optional `selfDependsOn(...)` lifetime modifier before function declarations. This extends *declaration-modifier* as follows:
+The new syntax also adds an optional `dependsOn(self:...)` lifetime modifier before function declarations. This extends *declaration-modifier* as follows:
 
 >
-> *declaration-modifier* → *self-lifetime-modifier* \
-> *self-lifetime-modifier* → **`selfDependsOn`** **`(`** *lifetime-dependent-list* **`)`**
+> *declaration-modifier* → **`dependsOn`** **`(`** **`self`** **`:`** *lifetime-dependent-list* **`)`**
 >
 
 The *lifetime-dependent* argument to the lifetime modifier is one of the following:

From 1859b9805bab5fd89eacdaf8910061c0740dd596 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Fri, 7 Jun 2024 05:26:55 -0700
Subject: [PATCH 27/59] Remove Future Direction: only limited to results

---
 proposals/NNNN-lifetime-dependency.md | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index dd1af7badf..4f0858309d 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -786,14 +786,6 @@ This was changed after we realized that there was in practice almost always a si
 
 ## Future Directions
 
-### Lifetime Dependencies for Escapable Types
-
-This proposal has deliberately limited the application of lifetime dependencies to return types that are nonescapable.
-This simplifies the model by identifying nonescapable types as exactly those types that can carry such dependencies.
-It also helps simplify the enforcement of lifetime constraints by guaranteeing that constrained values cannot escape before being returned.
-Most importantly, this restriction helps ensure that the new semantics (especially lifetime dependency inference) cannot accidentally break existing code.
-We expect that in the future, additional investigation can reveal a way to relax this restriction.
-
 ### Lifetime Dependencies for Tuples
 
 It should be possible to return a tuple where one part has a lifetime dependency.

From 6c80aca2684159d81fbc42475752eb2be3242e72 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Fri, 7 Jun 2024 07:31:09 -0700
Subject: [PATCH 28/59] Fix OwnedSpan ~Escapable typo.

---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 4f0858309d..0a0e0e27b5 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -978,7 +978,7 @@ struct View<Element>: ~Escapable {
 A scoped dependence normally cannot escape the lexical scope of its source variable. It may, however, be convenient to escape the source of that dependence along with any values that dependent on its lifetime. This could be done by moving the ownership of the source into a structure that preserves any dependence relationships. A function that returns a nonescapable type cannot currently depend on the scope of a consuming parameter. But we could lift that restriction provided that the consumed argument is moved into the return value, and that the return type preserves any dependence on that value:
 
 ```swift
-struct OwnedSpan<T>: ~Copyable & ~Escapable{
+struct OwnedSpan<T>: ~Copyable {
   let owner: any ~Copyable
   let span: dependsOn(scope owner) Span<T>
 

From 43dbc155c72e625b05ceef9ceccf87ec62578b80 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Fri, 7 Jun 2024 07:41:48 -0700
Subject: [PATCH 29/59] Tweak wording in the `ref1.drop` example.

---
 proposals/NNNN-lifetime-dependency.md | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 0a0e0e27b5..4ce3528f41 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -181,8 +181,10 @@ let ref1 = a.span() // ref1 cannot outlive a
 let ref2 = ref1.drop(4) // ref2 also cannot outlive a
 ```
 
-After `ref1.drop(4)`, the lifetime of `ref2` does not depend on `ref1`.
-Rather, `ref2` has **inherited** or **copied** `ref1`’s dependency on the lifetime of `a`.
+After `ref1.drop(4)`, the lifetime of `ref2` does not depend on `ref1`, which is consumed within the method. Instead,
+the `drop` method **copies** `ref1`s lifetime depenence onto `ref2`. `ref2` effectively **inherits** a lifetime
+dependency on `a`. We may refer to a lifetime dependence that has been copied from another value as an "inherited"
+dependence.
 
 #### Allowed Lifetime Dependencies
 

From d8f4cb3db580c57ee2d09d3cc244055d15141786 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Sun, 9 Jun 2024 08:18:06 -0700
Subject: [PATCH 30/59] New section: Immortal requirements.

---
 proposals/NNNN-lifetime-dependency.md | 33 ++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 4ce3528f41..18cd7b4546 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -389,7 +389,9 @@ extension Optional {
 }
 ```
 
-Once the escapable instance is constructed, it is limited in scope to the caller's function body since the caller only sees the static nonescapable type. If a dynamically escapable value needs to be returned further up the stack, that can be done by chaining multiple `dependsOn(immortal)` functions.
+The constructed instance is returned to the caller without any lifetime dependence. The caller can pass that instance
+along as an argument to other functions, but those functions cannot escape it. The instance can only be returned further
+up the call stack by chaining multiple `dependsOn(immortal)` functions.
 
 #### Depending on immutable global variables
 
@@ -403,6 +405,35 @@ func getStaticallyAllocated() -> dependsOn(immortal) BufferReference {
 }
 ```
 
+#### Immortal requirements
+
+`dependsOn(immortal)` requires the programmer to compose the dependent value from something that, in fact, has an immortal lifetime:
+
+```swift
+init() dependsOn(immortal) {
+  self.value = <global constant>
+}
+```
+
+`<global constant>` must be valid over the entire program.
+
+`dependsOn(immortal)` is not a way to suppress dependence in cases where the source value has unknown
+lifetime. Composing the result from a transient value, such as an UnsafePointer, is incorrect:
+
+```swift
+init(pointer: UnsafePointer<T>) dependsOn(immortal) {
+  self.value = pointer // 🛑 Incorrect
+}
+```
+
+We could run into the same problem with any transient value, like a file descriptor, or even a class object:
+
+```swift
+init() dependsOn(immortal) {
+  self.value = Object() // 🛑 Incorrect
+}
+```
+
 ### Depending on an escapable `BitwiseCopyable` value
 
 The source of a lifetime depenence may be an escapable `BitwiseCopyable` value. This is useful in the implementation of data types that internally use `UnsafePointer`:

From 5555ee6b19c1c1c6825b35117212053975284986 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Sun, 9 Jun 2024 08:18:19 -0700
Subject: [PATCH 31/59] New alternatives considered: Initializer syntax.

---
 proposals/NNNN-lifetime-dependency.md | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 18cd7b4546..b7f5b1a4b8 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -793,6 +793,27 @@ Removing a lifetime dependency constraint only affects existing source code in t
 
 ## Alternatives considered
 
+### Initializer syntax: result vs. inout syntax
+
+The programming model for initializers is that they return `self` (with an implicit return statement):
+
+`init(arg: ArgType) -> dependsOn(arg) Self`
+
+But some people have criticized this syntax. They prefer to think of an initializer as mutating `self`, which would be
+spelled:
+
+`dependsOn(self: arg) init(arg: ArgType)`
+
+We could adopt either or both of these options.
+
+In a future with component lifetimes the syntax would look like either:
+
+`init(arg1: Element, arg2: Element) -> dependsOn(a: arg1, b: arg2) Self {...}`
+
+or
+
+`dependsOn(self.a: arg1, self.b: arg2) init(arg1: Element, arg2: Element) ->  Self {...}`
+
 ### Different Position
 
 We propose above putting the annotation on the return value, which we believe matches the intuition that the method or property is producing this lifetime dependence alongside the returned value.

From eb1d88eea19800f1eee25de86ed16ac601b1f378 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Sat, 8 Jun 2024 04:53:53 -0700
Subject: [PATCH 32/59] Update Future component syntax.

---
 proposals/NNNN-lifetime-dependency.md | 44 +++++++++++++++++++++++++--
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index b7f5b1a4b8..5d4bbea512 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -324,6 +324,27 @@ We've discussed how a nonescapable result must be destroyed before the source of
   // 'span' now depends on both 'a1' and 'a2'.
 ```
 
+The general form of the `dependsOn` syntax is:
+
+> **dependsOn**(*target*: *source*)
+
+where `target` can be inferred from context:
+
+- Result modifiers go before the result type (after the `->` sigil)
+
+- Parameter modifiers go before the parameter type
+
+- `self` modifiers always go in front of the `func` declaration.
+
+Although `self` could be inferred, it must be spelled explicitly to avoid confusion with the common case of a result
+dependence.
+
+Example:
+
+```
+  dependsOn(self: arg1) func foo<T, R>(arg1: dependsOn(arg2) T, arg2: T) -> dependsOn(arg2) R
+```
+
 ### Dependent properties
 
 Structural composition is an important use case for nonescapable types. Getting or setting a nonescapable property requires lifetime dependence, just like a function result or an 'inout' parameter. There's no need for explicit annotation in these cases, because only one dependence is possible. A getter returns a value that depends on `self`. A setter replaces the current dependence from `self` with a dependence on `newValue`.
@@ -845,7 +866,7 @@ This was changed after we realized that there was in practice almost always a si
 It should be possible to return a tuple where one part has a lifetime dependency.
 For example:
 ```swift
-func f(a: consume A, b: B) -> (consume(a) C, B)
+func f(a: A, b: B) -> (dependsOn(a) C, B)
 ```
 We expect to address this in the near future in a separate proposal.
 
@@ -867,7 +888,7 @@ This could be exposed as an alternate spelling if there were sufficient demand.
 func f(arg1: Type1, arg2: Type2, arg3: Type3) -> dependsOn(0) ReturnType
 ```
 
-### Value component lifetime
+### Component lifetime
 
 In the current design, aggregating multiple values merges their scopes.
 
@@ -900,12 +921,29 @@ struct Container<Element>: ~Escapable {
   @lifetime
   var b: /*dependsOn(self.b)*/ Element
 
-  init(a: Element, b: Element) -> dependsOn(a -> .a, b -> .b) Self {...}
+  init(arg1: Element, arg2: Element) -> dependsOn(a: arg1, b: arg2) Self {...}
 }
 ```
 
 The nesting level of a component is the inverse of the nesting level of its lifetime. `a` and `b` are nested components of `Container`, but the lifetime of a `Container` instance is nested within both lifetimes of `a` and `b`.
 
+The general form of the `dependsOn` syntax should be thought of as:
+
+> **dependsOn**(*target*.*component*: *source*.*component*)
+
+where the `target` can be inferred from context, but not its component:
+
+Example:
+
+```
+  struct S: ~Escapable {
+    @lifetime
+    let a: T
+
+    dependsOn(self.a: arg1) func foo(arg1: dependsOn(a: arg2) S, arg2: T) -> dependsOn(a: arg2) S
+  }
+```
+
 ### Abstract lifetime components
 
 Lifetime dependence is not always neatly tied to stored properties. Say that our `Container` now holds multiple elements within its own storage. We can use a top-level `@lifetime` annotation to name an abstract lifetime for all the elements:

From a9ca58db48f2f4c080f90dac9361bb706767ed6e Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Mon, 10 Jun 2024 14:42:55 -0700
Subject: [PATCH 33/59] New alternative considered: dependsOn(unchecked)

to disable lifetime dependence checking
---
 proposals/NNNN-lifetime-dependency.md | 45 +++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 5d4bbea512..93c0edca7d 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -544,6 +544,15 @@ extension Span {
 
 Since `self.base` is an escapable value, it does not propagate the lifetime dependence of its container. Without the call to `unsafeLifetime`, `local` would be limited to the local scope of the value retrieved from `self.base`, and could not be returned from the method. In this example, `unsafeLifetime` communicates that all of the dependent state from `self` has been *copied* into `local`, and, therefore, `local` can persist after `self` is destroyed.
 
+`unsafeLifetime` can also be used to construct an immortal value where the compiler cannot prove immortality by passing a `Void` value as the source of the dependence:
+
+```swift
+init() dependsOn(immortal) {
+  self.value = getGlobalConstant() // OK: unchecked dependence.
+  self = unsafeLifetime(dependent: self, dependsOn: ())
+}
+```
+
 ## Detailed design
 
 ### Relation to ~Escapable
@@ -859,6 +868,42 @@ func f(arg1: borrow Array<Int>) -> borrow(arg1) Span<Int>
 ```
 This was changed after we realized that there was in practice almost always a single viable semantic for any given situation, so the additional refinement seemed unnecessary.
 
+### dependsOn(unchecked) to disable lifetime dependence checking
+
+A `dependsOn(unchecked)` annotation could allow programmers to disable lifetime dependence checking for a function result or argument. For example, the programmer may want to compose a nonescapable result from an immortal value that isn't visible to the compiler:
+
+```swift
+init() dependsOn(immortal) {
+  self.value = getGlobalConstant() // 🛑 ERROR: immortal dependence on a temporary value
+}
+```
+
+To avoid the error, the programmer could disable dependence checking on the function result altogether:
+
+```swift
+init() dependsOn(unchecked) {
+  self.value = getGlobalConstant() // OK: unchecked dependence.
+}
+```
+
+This poses a few problems:
+
+1. Declaring a result "unchecked" only affects checking within the function body; it doesn't affect checking in clients of the API, so really shouldn't be part of the API. In the example above, `dependsOn(immortal)` has the correct semantics at the API level.
+
+2. `dependsOn(unchecked)` is a blunt tool for opting out of safety. Experience shows that such tools are overused as workarounds for compiler errors without fixing the problem. A safety workaround should more precisely identify the source of unsafety.
+
+3. The more kewords we add to `dependsOn`, the more chance they will collide with a parameter name.
+
+`unsafeLifetime` is the propsed tool for disabling dependence checks. Passing `Void` as the dependence source is a reasonable way to convert a nonescaping value to an immortal value:
+
+
+```swift
+init() dependsOn(immortal) {
+  self.value = getGlobalConstant() // OK: unchecked dependence.
+  self = unsafeLifetime(dependent: self, dependsOn: ())
+}
+```
+
 ## Future Directions
 
 ### Lifetime Dependencies for Tuples

From 181050a15e538da25b1f2856779704ce04970606 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 11 Jun 2024 13:21:10 -0700
Subject: [PATCH 34/59] Remove redundant future direction: containers and their
 elements

---
 proposals/NNNN-lifetime-dependency.md | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 93c0edca7d..d47c4c9360 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -915,15 +915,6 @@ func f(a: A, b: B) -> (dependsOn(a) C, B)
 ```
 We expect to address this in the near future in a separate proposal.
 
-### Lifetime Dependencies for containers and their elements
-
-It should be possible to return containers with collections of lifetime-constrained elements.
-For example, a container may want to return a partition of its contents:
-```swift
-borrowing func chunks(n: Int) -> dependsOn(self) SomeList<dependsOn(self) Span<UInt8>>
-```
-We're actively looking into ways to support these more involved cases and expect to address this in a future proposal.
-
 ### Parameter index for lifetime dependencies
 
 Internally, the implementation records dependencies based on the parameter index.

From d7c1ac7315cb1b4c18a8c9528d3c97c2a31af620 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 11 Jun 2024 13:24:10 -0700
Subject: [PATCH 35/59] Move "Parameter index" section to Alternatives
 considered.

---
 proposals/NNNN-lifetime-dependency.md | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index d47c4c9360..c60cdbc1cb 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -904,6 +904,15 @@ init() dependsOn(immortal) {
 }
 ```
 
+### Parameter index for lifetime dependencies
+
+Internally, the implementation records dependencies based on the parameter index.
+This could be exposed as an alternate spelling if there were sufficient demand.
+
+```swift
+func f(arg1: Type1, arg2: Type2, arg3: Type3) -> dependsOn(0) ReturnType
+```
+
 ## Future Directions
 
 ### Lifetime Dependencies for Tuples
@@ -915,15 +924,6 @@ func f(a: A, b: B) -> (dependsOn(a) C, B)
 ```
 We expect to address this in the near future in a separate proposal.
 
-### Parameter index for lifetime dependencies
-
-Internally, the implementation records dependencies based on the parameter index.
-This could be exposed as an alternate spelling if there were sufficient demand.
-
-```swift
-func f(arg1: Type1, arg2: Type2, arg3: Type3) -> dependsOn(0) ReturnType
-```
-
 ### Component lifetime
 
 In the current design, aggregating multiple values merges their scopes.

From b01cd1e12562ac6cb13e4a3c1b0f4cd8c0b143f9 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 11 Jun 2024 13:33:48 -0700
Subject: [PATCH 36/59] Typo in example from "Depending on an escapable"

---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index c60cdbc1cb..b7c47d4736 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -496,7 +496,7 @@ extension Storage {
 let storage = Storage(...)
 storage.withUnsafeBufferPointer { buffer in
   let span = Span(unsafeBaseAddress: buffer.baseAddress!, count: buffer.count)
-  decode(span!) // âś… Safe: 'buffer' is always valid within the closure.
+  decode(span) // âś… Safe: 'buffer' is always valid within the closure.
 }
 ```
 

From 02fc95afe6da357587cac05be0522ab39869f3db Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Wed, 12 Jun 2024 02:59:16 -0700
Subject: [PATCH 37/59] Rename Array to ContiguousArray.

The examples all refer to a `span()` function. This is unimplementable for
`Array` because it might not have contiguous storage. An `Array` span requires a
`_read` accessor because we need to create a temporary copy of the Array when it
is discontiguous. But we can't talk about `_read` here because it hasn't been
proposed yet.
---
 proposals/NNNN-lifetime-dependency.md | 42 +++++++++++++--------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index b7c47d4736..e273813915 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -47,11 +47,11 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 An efficient way to provide one piece of code with temporary access to data stored in some other piece of code is with a pointer to the data in memory.
 Swift's `Unsafe*Pointer` family of types can be used here, but as the name implies, using these types can be error-prone.
 
-For example, suppose `Array` had a property `unsafeBufferPointer` that returned an `UnsafeBufferPointer` to the contents of the array.
+For example, suppose `ContiguousArray` had a property `unsafeBufferPointer` that returned an `UnsafeBufferPointer` to the contents of the array.
 Here's an attempt to use such a property:
 
 ```swift
-let array = getArrayWithData()
+let array = getContiguousArrayWithData()
 let buff = array.unsafeBufferPointer
 parse(buff) // <== 🛑 NOT SAFE!
 ```
@@ -111,11 +111,11 @@ In the most common cases, these constraints can be inferred automatically.
 
 To make the semantics clearer, we’ll begin by describing how one can explicitly specify a lifetime constraint in cases where the default inference rules do not apply.
 
-Let’s consider adding support for our hypothetical `Span` type to `Array`.
+Let’s consider adding support for our hypothetical `Span` type to `ContiguousArray`.
 Our proposal would allow you to declare an `array.span()` method as follows:
 
 ```swift
-extension Array {
+extension ContiguousArray {
   borrowing func span() -> dependsOn(self) Span<Element> {
     ... construct a Span ...
   }
@@ -138,7 +138,7 @@ Let’s consider another hypothetical type: a `MutatingSpan<T>` type that could
 Here's one way such a value might be produced:
 
 ```swift
-func mutatingSpan(to: inout Array, count: Int) -> dependsOn(to) MutatingSpan<Element> {
+func mutatingSpan(to: inout ContiguousArray, count: Int) -> dependsOn(to) MutatingSpan<Element> {
   ... construct a MutatingSpan ...
 }
 ```
@@ -153,7 +153,7 @@ Similar to the previous example:
 
 In both this and the previous case, the lifetime of the return value is "scoped" to the lifetime of the original value.
 Because lifetime dependencies can only be attached to nonescapable values, types that contain pointers will generally need to be nonescapable in order to provide safe semantics.
-As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as an Array or similar container) is providing a nonescapable value (such as the `Span` or `MutatingSpan` in these examples).
+As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as a ContiguousArray or similar container) is providing a nonescapable value (such as the `Span` or `MutatingSpan` in these examples).
 
 #### Copied Lifetime Dependency
 
@@ -176,7 +176,7 @@ If the original `Span` was borrowing some array, the new `Span` will continue to
 
 This supports coding patterns such as this:
 ```swift
-let a: Array<Int>
+let a: ContiguousArray<Int>
 let ref1 = a.span() // ref1 cannot outlive a
 let ref2 = ref1.drop(4) // ref2 also cannot outlive a
 ```
@@ -317,9 +317,9 @@ extension Span {
 We've discussed how a nonescapable result must be destroyed before the source of its lifetime dependence. Similarly, a dependent argument must be destroyed before an argument that it depends on. The difference is that the dependent argument may already have a lifetime dependence when it enters the function. The new function argument dependence is additive, because the call does not guarantee reassignment. Instead, passing the 'inout' argument is like a conditional reassignment. After the function call, the dependent argument carries both lifetime dependencies.
 
 ```swift
-  let a1: Array<Int> = ...
+  let a1: ContiguousArray<Int> = ...
   var span = a1.span()
-  let a2: Array<Int> = ...
+  let a2: ContiguousArray<Int> = ...
   mayReassign(span: &span, to: a2)
   // 'span' now depends on both 'a1' and 'a2'.
 ```
@@ -680,10 +680,10 @@ If a function, method, or initializer has a nonescapable return value, does not
 
 ### Dependency semantics by example
 
-This section illustrates the semantics of lifetime dependence one example at a time for each interesting variation. The following helper functions will be useful: `Array.span()` creates a scoped dependence to a nonescapable `Span` result, `copySpan()` creates a copied dependence to a `Span` result, and `parse` uses a `Span`.
+This section illustrates the semantics of lifetime dependence one example at a time for each interesting variation. The following helper functions will be useful: `ContiguousArray.span()` creates a scoped dependence to a nonescapable `Span` result, `copySpan()` creates a copied dependence to a `Span` result, and `parse` uses a `Span`.
 
 ```swift
-extension Array {
+extension ContiguousArray {
   // The returned span depends on the scope of Self.
   borrowing func span() -> /* dependsOn(scoped self) */ Span<Element> { ... }
 }
@@ -697,7 +697,7 @@ func parse(_ span: Span<Int>) { ... }
 #### Scoped dependence on an immutable variable
 
 ```swift
-let a: Array<Int> = ...
+let a: ContiguousArray<Int> = ...
 let span: Span<Int>
 do {
   let a2 = a
@@ -715,7 +715,7 @@ Let's contrast scoped dependence shown above with copied dependence on a variabl
 An assignment that copies or moves a nonescapable value from one variable into another **copies** any lifetime dependence from the source value to the destination value. Thus, variable assignment has the same lifetime copy semantics as passing an argument using a `dependsOn()` annotation *without* a `scoped` keyword. So, the statement `let temp = span` has identical semantics to `let temp = copySpan(span)`.
 
 ```swift
-let a: Array<Int> = arg
+let a: ContiguousArray<Int> = arg
 let final: Span<Int>
 do {
   let span = a.span()
@@ -746,7 +746,7 @@ extension Span {
 A dependence may be copied from a mutable ('inout') variable. In that case, the dependence is inherited from whatever value the mutable variable holds when it is accessed.
 
 ```swift
-let a: Array<Int> = ...
+let a: ContiguousArray<Int> = ...
 var prefix: Span<Int>
 do {
   var temp = a.span()
@@ -761,7 +761,7 @@ parse(prefix) // âś… Safe: still within lifetime of 'a'
 Now, let's return to scoped dependence, this time on a mutable variable. This is where exclusivity guarantees come into play. A scoped depenendence extends an access of the mutable variable across all uses of the dependent value. If the variable mutates again before the last use of the dependent, then it is an exclusivity violation.
 
 ```swift
-let a: Array<Int> = ...
+let a: ContiguousArray<Int> = ...
 a[i] = ...
 let span = a1.span()
 parse(span) // âś… Safe: still within 'span's access on 'a'
@@ -777,7 +777,7 @@ We've described how a mutable variable can be the source of a lifetime dependenc
 
 ```swift
 func reassign(_ span: inout Span<Int>) {
-  let a: Array<Int> = ...
+  let a: ContiguousArray<Int> = ...
   span = a.span() // 🛑 Error: 'span' escapes the scope of 'a'
 }
 ```
@@ -797,9 +797,9 @@ func reassignWithArgDependence(_ span: dependsOn(arg) inout [Int], _ arg: [Int])
 'inout' argument dependence behaves like a conditional reassignment. After the call, the variable passed to the 'inout' argument has both its original dependence along with a new dependence on the argument that is the source of the argument dependence.
 
 ```swift
-let a1: Array<Int> = arg
+let a1: ContiguousArray<Int> = arg
 do {
-  let a2: Array<Int> = arg
+  let a2: ContiguousArray<Int> = arg
   var span = a1.span()
   testReassignArgDependence(&span, a2) // creates a conjoined dependence
   parse(span) // âś… OK: within the lifetime of 'a1' & 'a2'
@@ -850,21 +850,21 @@ We propose above putting the annotation on the return value, which we believe ma
 It would also be possible to put an annotation on the parameters instead:
 
 ```swift
-func f(@resultDependsOn arg1: Array<Int>) -> Span<Int>
+func f(@resultDependsOn arg1: ContiguousArray<Int>) -> Span<Int>
 ```
 
 Depending on the exact language in use, it could also be more natural to put the annotation after the return value.
 However, we worry that this hides this critical information in cases where the return type is longer or more complex.
 
 ```swift
-func f(arg1: Array<Int>) -> Span<Int> dependsOn(arg1)
+func f(arg1: ContiguousArray<Int>) -> Span<Int> dependsOn(arg1)
 ```
 
 ### Different spellings
 
 An earlier version of this proposal advocated using the existing `borrow`/`mutate`/`consume`/`copy` keywords to specify a particular lifetime dependency semantic:
 ```swift
-func f(arg1: borrow Array<Int>) -> borrow(arg1) Span<Int>
+func f(arg1: borrow ContiguousArray<Int>) -> borrow(arg1) Span<Int>
 ```
 This was changed after we realized that there was in practice almost always a single viable semantic for any given situation, so the additional refinement seemed unnecessary.
 

From de45422d6ca57fb51a1f0ed19b2f66ae21ce2411 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Wed, 12 Jun 2024 03:55:14 -0700
Subject: [PATCH 38/59] New example: Escapable properties in a nonescapable
 type

---
 proposals/NNNN-lifetime-dependency.md | 29 ++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index e273813915..bc4418d158 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -734,11 +734,11 @@ First, let's add a mutable method to `Span`:
 
 ```swift
 extension Span {
-  mutating func droppingPrefix(length: Int) -> /* dependsOn(self) */ Span<T> {
-    let result = Span(base: base, count: length)
+  mutating func removePrefix(length: Int) -> /* dependsOn(self) */ Span<T> {
+    let prefix = Span(base: base, count: length)
     self.base += length
     self.count -= length
-    return result
+    return prefix
   }
 }
 ```
@@ -807,6 +807,29 @@ do {
 parse(span) // 🛑 Error: 'span' escapes the scope of 'a2'
 ```
 
+#### Escapable properties in a nonescapable type
+
+An escapable type inevitably contains nonescapable properties. In our `Span` example, the `base` pointer and `count`
+length are both escapable. Accessing an escapable property drops the dependence:
+
+```swift
+  let pointer: UnsafePointer<T>
+  do {
+    let span = Span(unsafeBaseAddress: pointer, count: 1)
+    pointer = span.base
+  }
+  _ = pointer // âś… OK: pointer has no lifetime dependence
+```
+
+Internal mutation of a nonescapable type does not create any new dependence and does not require any annotation:
+
+```swift
+  mutating /* dependsOn(self: self) */ func skipPrefix(length: Int) {
+    self.base += length  // âś… OK: assigns `base` to a copy of the temporary value
+    self.count -= length // âś… OK: assigns `count` to a copy of the temporary value
+  }
+```
+
 ## Source compatibility
 
 Everything discussed here is additive to the existing Swift grammar and type system.

From 5b0fd846883f92584a9f2f3d8f0b741fed60780f Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Sun, 9 Jun 2024 08:01:14 -0700
Subject: [PATCH 39/59] Changelog entries

---
 proposals/NNNN-lifetime-dependency.md | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index bc4418d158..f54f3e9ff5 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -35,6 +35,14 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
   - Protocol lifetime requirements
   - Structural lifetime dependencies
 
+**Edited** (June 9, 2024):
+
+- New section: Immortal requirements
+- New alternative considered: Initializer syntax
+- New alternative considered: dependsOn(unchecked) to disable lifetime dependence checking
+- Updated future direction: component lifetime syntax
+- New example: Escapable properties in a nonescapable type
+
 #### See Also
 
 * [Forum discussion of Non-Escapable Types and Lifetime Dependency](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency)

From 9acaba8a5d20d2f672550c872cabcae92e0ffcee Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Fri, 14 Jun 2024 10:58:37 -0700
Subject: [PATCH 40/59] Fix a grammar typo.

---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index f54f3e9ff5..52be7ca99f 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -599,7 +599,7 @@ This new syntax adds an optional `dependsOn(...)` lifetime modifier just before
 > *function-result* → **`->`** *attributes?* *lifetime-modifiers?* *type* \
 > *lifetime-modifiers* → *lifetime-modifier* *lifetime-modifiers?* \
 > *lifetime-modifier* → **`dependsOn`** **`(`** *lifetime-dependent-list* **`)`** \
-> *lifetime-dependence-list* → *lifetime-dependent* | *lifetime-dependence-source* **`,`** *lifetime-dependent-list*
+> *lifetime-dependence-list* → *lifetime-dependence-source* **`,`** *lifetime-dependent-list*
 > *lifetime-dependence-source* → **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name* | **`immortal`**
 >
 > *parameter-type-annotation* → : *attributes?* *lifetime-modifiers?* *parameter-modifier*? *type*

From 51832e85d957f22bacdb5fa650425cf98ec10866 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Fri, 14 Jun 2024 11:02:51 -0700
Subject: [PATCH 41/59] Fix a typo in the dependent parameters example.

---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 52be7ca99f..e6a0f2c8fa 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -307,7 +307,7 @@ We expect these implicit inferences to cover most cases, with the explicit form
 Normally, lifetime dependence is required when a nonescapable function result depends on an argument to that function. In some rare cases, however, a nonescapable function parameter may depend on another argument to that function. Consider a function with an `inout` parameter. The function body may reassign that parameter to a value that depends on another parameter. This is similar in principle to a result dependence.
 
 ```swift
-func mayReassign(span: dependsOn(a) inout [Int], to a: [Int]) {
+func mayReassign(span: dependsOn(a) inout Span<Int>, to a: [Int]) {
   span = a.span()
 }
 ```

From 0ed7906a7a81c5002048c5cc27f3217e0e4c6a73 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Fri, 14 Jun 2024 11:11:46 -0700
Subject: [PATCH 42/59] Typo: fix two more cases of Array -> ContiguousArray
 renaming.

---
 proposals/NNNN-lifetime-dependency.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index e6a0f2c8fa..78012b4dd4 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -307,7 +307,7 @@ We expect these implicit inferences to cover most cases, with the explicit form
 Normally, lifetime dependence is required when a nonescapable function result depends on an argument to that function. In some rare cases, however, a nonescapable function parameter may depend on another argument to that function. Consider a function with an `inout` parameter. The function body may reassign that parameter to a value that depends on another parameter. This is similar in principle to a result dependence.
 
 ```swift
-func mayReassign(span: dependsOn(a) inout Span<Int>, to a: [Int]) {
+func mayReassign(span: dependsOn(a) inout Span<Int>, to a: ContiguousArray<Int>) {
   span = a.span()
 }
 ```
@@ -795,7 +795,7 @@ func reassign(_ span: inout Span<Int>) {
 If a function takes a nonescapable 'inout' argument, it may only reassign that argument if it is marked dependent on another function argument that provies the source of the dependence.
 
 ```swift
-func reassignWithArgDependence(_ span: dependsOn(arg) inout [Int], _ arg: [Int]) {
+func reassignWithArgDependence(_ span: dependsOn(arg) inout ContiguousArray<Int>, _ arg: ContiguousArray<Int>) {
   span = arg.span() //  âś… OK: 'span' already depends on 'arg' in the caller's scope.
 }
 ```

From a969447b1981133867babb424e8b6aa6299ab648 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Thu, 20 Jun 2024 16:08:54 -0700
Subject: [PATCH 43/59] Update the free-standing function inference rules.

---
 proposals/NNNN-lifetime-dependency.md | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 78012b4dd4..68bb1b8fa7 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -673,14 +673,11 @@ If there is no explicit lifetime dependency, we will automatically infer one acc
 **For methods where the return value is nonescapable**, we will infer a dependency against self, depending on the mutation type of the function.
 Note that this is not affected by the presence, type, or modifier of any other arguments to the method.
 
-**For a free or static functions or initializers with at least one argument,** we will infer a lifetime dependency when all of the following are true:
+**For a free or static functions or initializers with at least one argument,** we will infer a lifetime dependency when the return value is nonescapable and exactly one argument that satisfies any of the following:
+  - is nonescapable, or
+  - is non-BitwiseCopyable and has an explicit `borrowing`, or `inout` convention
 
-* the return value is nonescapable,
-* there is exactly one argument that satisfies any of the following:
-  - is either noncopyable or nonescapable, or
-  - has an explicit `borrowing`, `consuming`, or `inout` convention specified
-
-In this case, the compiler will infer a dependency on the unique argument identified by this last set of conditions.
+In this case, the compiler will infer a dependency on the unique argument identified by these conditions.
 
 **In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
 If a function, method, or initializer has a nonescapable return value, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.

From e1d364eea79863ed80d737991ec2da788760052f Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Fri, 21 Jun 2024 11:19:15 -0700
Subject: [PATCH 44/59] Added future directions: Function type syntax and
 closures

---
 proposals/NNNN-lifetime-dependency.md | 84 +++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 68bb1b8fa7..2be3a8abe3 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -952,6 +952,90 @@ func f(a: A, b: B) -> (dependsOn(a) C, B)
 ```
 We expect to address this in the near future in a separate proposal.
 
+### Function type syntax
+
+A function that returns a nonescapable type cannot currently be passed as a nonescaping closure because its dependence information would be lost.
+
+```swift
+func f(arg: ArgType) -> dependsOn(arg) NEType
+
+func g1(closure: (ArgType) -> NEType)
+
+{
+  g1(closure: f) // 🛑 ERROR: function type mismatch 
+}
+```
+
+To address this shortcoming, we plan to extend the `dependsOn(...)` modifier for use in function types. Since function
+types have no parameter names, the parameter position will be identified by an integer literal:
+
+```swift
+func g2(closure: (ArgType) -> dependsOn(0) NE)
+
+{
+  g2(closure: f) // âś… OK
+}
+```
+
+The parameter index syntax is consistent with how dependencies are already represented internally and in mangled names.
+
+We expect most closures that return nonescapable types to be dependent on the closure context rather than a closure
+parameter--this will be the normal case for passing methods as nonescaping closures. A closure context dependence will
+not affect the spelling of the function type.
+
+### Lifetime dependence for closures
+
+In "Function type syntax", we propose that function types can have explicit `dependsOn` modifiers. When a function type
+returns a nonescapable value but has no explicit `dependsOn` modifier, we plan to infer a dependence on the closure
+context:
+
+```swift
+func g1(closure: () -> NEType) // Inferred: NEType depends on 'closure'
+```
+
+For closure declarations, lifetime dependencies can be inferred on the combined list of captures and closure parameters
+following the same rule as free standing functions. We can infer a lifetime dependence if the closure's return value is
+nonescapable, and exactly one closure capture or closure parameter satisfies any of the following:
+
+  - is nonescapable, or
+  - is non-BitwiseCopyable and has an explicit `borrowing`, or `inout` convention
+
+A dependence can be inferred on a closure capture as follows:
+
+```swift
+func f(arg: borrowing ArgType) -> dependsOn(arg) NEType
+
+func foo(source: borrowing ArgType) {
+  g1 { f(arg: source) } // âś… Inferred: 'closure' result depends on captured 'source'
+}
+```
+
+An explicit dependence on a closure capture can be spelled:
+
+```swift
+func foo(source: borrowing ArgType) {
+  g1 { () -> dependsOn(source) NEType in f(arg: source) }
+}
+```
+
+Similarly, a dependence can be inferred on a closure parameter:
+
+```swift
+func g2(closure: (borrowing ArgType) -> dependsOn(0) NEType)
+
+{
+  g2 { (source: borrowing ArgType) in f(arg: source) } // âś… Inferred: 'closure' result depends on 'source' parameter
+}
+```
+
+An explicit dependence on a closure parameter can be spelled:
+
+```swift
+{
+  g2 { (source: borrowing ArgType) -> dependsOn(source) NEType in f(arg: source) } // âś… Inferred: 'closure' result depends on 'source' parameter
+}
+```
+
 ### Component lifetime
 
 In the current design, aggregating multiple values merges their scopes.

From 9583bd7a79d1a7750d46ea766f9c308e0ea43fb2 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Wed, 10 Jul 2024 10:49:54 -0700
Subject: [PATCH 45/59] Add an alternative spelling: `lifetime` vs.
 `dependsOn`.

---
 proposals/NNNN-lifetime-dependency.md | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 2be3a8abe3..c134a68c12 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -896,6 +896,18 @@ func f(arg1: borrow ContiguousArray<Int>) -> borrow(arg1) Span<Int>
 ```
 This was changed after we realized that there was in practice almost always a single viable semantic for any given situation, so the additional refinement seemed unnecessary.
 
+The currently proposed `dependsOn` spelling was chosen to convey the direction of the dependence, as in:
+
+    func foo(a: A, b: B) -> dependsOn(a) R
+
+This does, however, introduce compound keyword. Alternatively, we could use a simpler `lifetime` keyword, which better matches the feature description. The general syntax would then be:
+
+> **lifetime**(*target*: [scoped] *source*)
+
+APIs with ambiguous depenencies would then typically be spelled:
+
+    func foo(a: A, b: B) -> lifetime(a) R
+
 ### dependsOn(unchecked) to disable lifetime dependence checking
 
 A `dependsOn(unchecked)` annotation could allow programmers to disable lifetime dependence checking for a function result or argument. For example, the programmer may want to compose a nonescapable result from an immortal value that isn't visible to the compiler:

From f337c2fd0b1330c2389f76203e4cecc4a02761a0 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Wed, 31 Jul 2024 10:08:09 -0700
Subject: [PATCH 46/59] Remove the Alternative: Initializer syntax: result vs.
 inout syntax

This section was a distraction. Changing the position of `dependsOn`
for initializers is not something we need to consider initially.
---
 proposals/NNNN-lifetime-dependency.md | 22 ----------------------
 1 file changed, 22 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index c134a68c12..1e49199ed5 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -38,7 +38,6 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 **Edited** (June 9, 2024):
 
 - New section: Immortal requirements
-- New alternative considered: Initializer syntax
 - New alternative considered: dependsOn(unchecked) to disable lifetime dependence checking
 - Updated future direction: component lifetime syntax
 - New example: Escapable properties in a nonescapable type
@@ -851,27 +850,6 @@ Removing a lifetime dependency constraint only affects existing source code in t
 
 ## Alternatives considered
 
-### Initializer syntax: result vs. inout syntax
-
-The programming model for initializers is that they return `self` (with an implicit return statement):
-
-`init(arg: ArgType) -> dependsOn(arg) Self`
-
-But some people have criticized this syntax. They prefer to think of an initializer as mutating `self`, which would be
-spelled:
-
-`dependsOn(self: arg) init(arg: ArgType)`
-
-We could adopt either or both of these options.
-
-In a future with component lifetimes the syntax would look like either:
-
-`init(arg1: Element, arg2: Element) -> dependsOn(a: arg1, b: arg2) Self {...}`
-
-or
-
-`dependsOn(self.a: arg1, self.b: arg2) init(arg1: Element, arg2: Element) ->  Self {...}`
-
 ### Different Position
 
 We propose above putting the annotation on the return value, which we believe matches the intuition that the method or property is producing this lifetime dependence alongside the returned value.

From 3b6439cee64fb9b3fe467b2ab2604255d1af1fee Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Wed, 31 Jul 2024 10:12:26 -0700
Subject: [PATCH 47/59] Add Alternative: @lifetime annotation and where clause.

---
 proposals/NNNN-lifetime-dependency.md | 68 ++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 1e49199ed5..a849330001 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -42,6 +42,11 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 - Updated future direction: component lifetime syntax
 - New example: Escapable properties in a nonescapable type
 
+**Edited** (July 31, 2024)
+
+- New alternative considered: @lifetime annotation
+- New alternative considered: where clause
+
 #### See Also
 
 * [Forum discussion of Non-Escapable Types and Lifetime Dependency](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency)
@@ -878,7 +883,7 @@ The currently proposed `dependsOn` spelling was chosen to convey the direction o
 
     func foo(a: A, b: B) -> dependsOn(a) R
 
-This does, however, introduce compound keyword. Alternatively, we could use a simpler `lifetime` keyword, which better matches the feature description. The general syntax would then be:
+This does, however, introduce a keyword with a compound name. Alternatively, we could use a simpler `lifetime` keyword, which better matches the feature description. The general syntax would then be:
 
 > **lifetime**(*target*: [scoped] *source*)
 
@@ -886,6 +891,67 @@ APIs with ambiguous depenencies would then typically be spelled:
 
     func foo(a: A, b: B) -> lifetime(a) R
 
+### @lifetime annotation
+
+Instead of committing to a final, lightweight syntax, we can start with a single `@lifetime` annotation. It would take this form:
+
+```
+@lifetime(target1.component: [copy|mutate|borrow] source1.component)
+@lifetime(target2.component: [copy|mutate|borrow] source2.component)
+func foo(...)
+```
+
+`target` can be `self`, any parameter name, or, most commonly an empty string which implies the function result. `source` can be `self` or any parameter name. The most common usage would be:
+
+```
+@lifetime(copy arg)
+func foo(arg: Arg1) -> R {}
+```
+
+The `.component` qualifier is only relevant once we have component lifetimes. See the "Component lifetime" section below.
+
+An annotation has some advantages over a lighter-weight type modifier sytax:
+
+The `@` sigil is helpful to distinguish lifetime dependence information from regular function syntax.
+
+A position-independent annotation has an advantage that the fully expressive syntax is more self-evident. This makes it easier to educate reviewers about what is possible with the syntax.
+
+The type modifier can occur in any type position within a function signature, in including before the `func` keyword for the 'self' type. This has potential readability problems when it comes to more complicated cases. Nested parentheses (`dependsOn(...)`) that can occur anywhere in the signature are visually confusing.
+
+In the future, the single `@lifetime` annotation could be a useful modifier for other kinds declarations such as types and properties:
+
+```
+// Allow two components to have distinct lifetimes...
+struct Pair<T: ~Escapable> {
+  @lifetime
+  var x: T
+
+  @lifetime
+  var y: T
+}
+
+// Allow two components to have dependent lifetimes...
+struct Node: ~Escapable {
+  @lifetime
+  var parent: Node
+
+  @lifetime(parent)
+  var child: Node
+}
+
+// Declare an abstract lifetime and alias it with another lifetime.
+@lifetime(elements: storage.elements)
+struct Container {
+  var storage: Storage
+}
+```
+
+### `where` clause
+
+Some have advocated for a `where` clause on the function declaration. The function name could stand-in for its result, and directionality could be indicated with a comparison operator:
+
+`func foo(arg: Arg) -> R where lifetime(foo) < lifetime([copy|borrow|mutate] arg)`
+
 ### dependsOn(unchecked) to disable lifetime dependence checking
 
 A `dependsOn(unchecked)` annotation could allow programmers to disable lifetime dependence checking for a function result or argument. For example, the programmer may want to compose a nonescapable result from an immortal value that isn't visible to the compiler:

From ac43daae330e6f4b94827befb39b49e104d447fd Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Wed, 31 Jul 2024 23:20:02 -0700
Subject: [PATCH 48/59] Simplified implicit lifetime dependencies

Added the same-type inference rule.
---
 proposals/NNNN-lifetime-dependency.md | 61 ++++++++++++++++-----------
 1 file changed, 36 insertions(+), 25 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index a849330001..2f0ff33041 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -46,6 +46,7 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 
 - New alternative considered: @lifetime annotation
 - New alternative considered: where clause
+- Simplified implicit lifetime dependencies and added same-type rule
 
 #### See Also
 
@@ -257,12 +258,11 @@ init(arg: <parameter-convention> ArgType) -> dependsOn(arg) Self
 
 ### Implicit Lifetime Dependencies
 
-The syntax above allows developers to explicitly annotate lifetime dependencies in their code.
-But because the possibilities are limited, we can usually allow the compiler to infer a suitable dependency.
-The detailed rules are below, but generally we require that the return type be nonescapable and that there be one “obvious” source for the dependency.
+The syntax above allows developers to explicitly annotate lifetime dependencies in their code.  But because the possibilities are limited, we can usually allow the compiler to infer a suitable dependency.  The detailed rules are below, but generally we require that the return type be nonescapable and that there be an “obvious” source for the dependency.
 
-In particular, we can infer a lifetime dependency on `self` for any method that returns a nonescapable value.
-As above, the details vary depending on whether `self` is escapable or nonescapable:
+#### Self dependence
+
+We can infer a lifetime dependency on `self` for any method that returns a nonescapable value. As above, the details vary depending on whether `self` is escapable or nonescapable:
 
 ```swift
 struct NonescapableType: ~Escapable { ... }
@@ -286,25 +286,21 @@ struct NEStruct: ~Escapable {
 }
 ```
 
-For free or static functions or initializers, we can infer a lifetime dependency when the return value is nonescapable and there is only one obvious argument that can serve as the source of the dependency.
-For example:
+#### Same-type dependence
 
-```swift
-struct NEType: ~Escapable { ... }
+For any function or method that returns a nonescapable type, we infer a copied lifetime dependency on all parameters of the same type.
 
-// If there is only one argument with an explicit parameter convention:
-func f(..., arg1: borrowing Type1, ...) -> /* dependsOn(arg1) */ NEType
+`func foo<T: ~Escapable, U: ~Escapable, R: ~Escapable>(x: T, y: U) -> R { ... }`
 
-// Or there is only one argument that is `~Escapable`:
-func g(..., arg2: NEType, ...) -> /* dependsOn(arg2) */ NEType
+implies:
 
-// If there are multiple possible arguments that we might depend
-// on, we require an explicit dependency:
-// 🛑 Cannot infer lifetime dependency since `arg1` and `arg2` are both candidates
-func g(... arg1: borrowing Type1, arg2: NEType, ...) -> NEType
+```
+-> dependsOn(x) where R == T
+-> dependsOn(y) where R == U
+-> dependsOn(x, y) where R == T == U
 ```
 
-We expect these implicit inferences to cover most cases, with the explicit form only occasionally being necessary in practice.
+This is particularly helpful for Generic APIs. With this rule, indicating that a generic parameter is `~Escapable` should usually be sufficient to infer the correct lifetime dependence.
 
 ### Dependent parameters
 
@@ -672,20 +668,35 @@ The implications of mutation modifiers and argument type on the resulting lifeti
 
 ### Inference Rules
 
-If there is no explicit lifetime dependency, we will automatically infer one according to the following rules:
+If there is no explicit lifetime dependency on the nonescapable result of a method or function, we will attempt to infer dependencies automatically according the following rules:
 
-**For methods where the return value is nonescapable**, we will infer a dependency against self, depending on the mutation type of the function.
-Note that this is not affected by the presence, type, or modifier of any other arguments to the method.
+1. For methods where the return value is nonescapable, we will infer a dependency against `self`. If `self` is nonescapable, then we infer a copying dependency. If `self` is escapable, and the method is `borrowing` or `mutating`, then we infer a scoped dependency.
 
-**For a free or static functions or initializers with at least one argument,** we will infer a lifetime dependency when the return value is nonescapable and exactly one argument that satisfies any of the following:
-  - is nonescapable, or
-  - is non-BitwiseCopyable and has an explicit `borrowing`, or `inout` convention
+2. For methods, functions, and initializers where the return value is nonescapable, we infer a copied lifetime dependency on all parameters of the same (nonescapable) type, including the implicit `self` parameter.
 
-In this case, the compiler will infer a dependency on the unique argument identified by these conditions.
+3. For functions and initializers that have a nonescapable return value and a single parameter, we infer dependence on that parameter. If the parameter is nonescapable, then we infer a copying dependency; otherwise, we infer a scoped dependency.
+
+For all inference rules, the type of dependence is the same as an explicit `dependsOn(argument)` on the same argument without any `scoped` qualifier based on the argument's type.
 
 **In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
 If a function, method, or initializer has a nonescapable return value, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
 
+We infer dependencies according to all applicable rules. Here, both rule #1 and #2 apply:
+
+```
+struct NE: ~Escapable { ... }
+struct E {
+  func foo(ne: NE) -> /* dependsOn(self, ne) */ NE
+}
+```
+
+Here, both rule #2 and #3 apply:
+
+```
+struct NE {
+  init(ne: NE) -> /* dependsOn(ne) */ Self
+}
+```
 
 ### Dependency semantics by example
 

From 5cd2fd3b780517560bec7716736e8f602db371b2 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Tue, 13 Aug 2024 16:52:46 -0700
Subject: [PATCH 49/59] Fix inference rules to be sequenced.

---
 proposals/NNNN-lifetime-dependency.md | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 2f0ff33041..bab21e1a89 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -48,6 +48,9 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 - New alternative considered: where clause
 - Simplified implicit lifetime dependencies and added same-type rule
 
+**Edited** (Aug 13, 2024)
+- Revised the same-type rule
+
 #### See Also
 
 * [Forum discussion of Non-Escapable Types and Lifetime Dependency](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency)
@@ -302,6 +305,8 @@ implies:
 
 This is particularly helpful for Generic APIs. With this rule, indicating that a generic parameter is `~Escapable` should usually be sufficient to infer the correct lifetime dependence.
 
+For methods, if `self` is the same type as the result, the same-type rule also applies, resulting in a copied dependence on `self`. This case overlaps with the aforementioned self dependence rule above and has the same effect.
+
 ### Dependent parameters
 
 Normally, lifetime dependence is required when a nonescapable function result depends on an argument to that function. In some rare cases, however, a nonescapable function parameter may depend on another argument to that function. Consider a function with an `inout` parameter. The function body may reassign that parameter to a value that depends on another parameter. This is similar in principle to a result dependence.
@@ -668,11 +673,11 @@ The implications of mutation modifiers and argument type on the resulting lifeti
 
 ### Inference Rules
 
-If there is no explicit lifetime dependency on the nonescapable result of a method or function, we will attempt to infer dependencies automatically according the following rules:
+If there is no explicit lifetime dependency on the nonescapable result of a method or function, we will attempt to infer dependencies automatically according these rules in the following order. Subsequent rules are only considered if the prior rules do not generate any inferred dependencies:
 
-1. For methods where the return value is nonescapable, we will infer a dependency against `self`. If `self` is nonescapable, then we infer a copying dependency. If `self` is escapable, and the method is `borrowing` or `mutating`, then we infer a scoped dependency.
+1. For methods, functions, and initializers where the return value is nonescapable, we infer a copied lifetime dependency on all parameters of the same nonescapable type. For methods, this rule applies to the implicit `self` parameter like any other parameter: if `self` has the same type as the nonescapable result, then we infer a copied dependency.
 
-2. For methods, functions, and initializers where the return value is nonescapable, we infer a copied lifetime dependency on all parameters of the same (nonescapable) type, including the implicit `self` parameter.
+2. For methods where the return value is nonescapable, we will infer a dependency against `self`. If `self` is nonescapable, then we infer a copying dependency. If `self` is escapable, and the method is `borrowing` or `mutating`, then we infer a scoped dependency.
 
 3. For functions and initializers that have a nonescapable return value and a single parameter, we infer dependence on that parameter. If the parameter is nonescapable, then we infer a copying dependency; otherwise, we infer a scoped dependency.
 
@@ -681,16 +686,18 @@ For all inference rules, the type of dependence is the same as an explicit `depe
 **In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
 If a function, method, or initializer has a nonescapable return value, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
 
-We infer dependencies according to all applicable rules. Here, both rule #1 and #2 apply:
+Consider an example that matches both rule #1 and #2:
 
 ```
 struct NE: ~Escapable { ... }
 struct E {
-  func foo(ne: NE) -> /* dependsOn(self, ne) */ NE
+  func foo(ne: NE) -> /* dependsOn(ne) */ NE
 }
 ```
 
-Here, both rule #2 and #3 apply:
+`foo` will not depend on self because rule #1 takes precedence over rule #2.
+
+In this example, both rule #2 and #3 match but are simply redundant:
 
 ```
 struct NE {

From 0a4392f09d0cd7113d72cfa0bc0372777f725b45 Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Thu, 15 Aug 2024 15:05:54 -0700
Subject: [PATCH 50/59] In the lifetime annotation example, add an argument
 label.

To clarify that the annotation refers to the parameter name, not the
label.
---
 proposals/NNNN-lifetime-dependency.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index bab21e1a89..45a9828642 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -923,7 +923,7 @@ func foo(...)
 
 ```
 @lifetime(copy arg)
-func foo(arg: Arg1) -> R {}
+func foo(label arg: Arg1) -> R {}
 ```
 
 The `.component` qualifier is only relevant once we have component lifetimes. See the "Component lifetime" section below.

From b841b472acf9ca9c5112409cbe368f368be64d4e Mon Sep 17 00:00:00 2001
From: Andrew Trick <atrick@apple.com>
Date: Mon, 19 Aug 2024 10:39:23 -0700
Subject: [PATCH 51/59] Update Future Direction: Lifetime dependence for
 closures

---
 proposals/NNNN-lifetime-dependency.md | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 45a9828642..08c9fa5aaf 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -51,6 +51,9 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 **Edited** (Aug 13, 2024)
 - Revised the same-type rule
 
+**Edited** (Aug 19, 2024)
+- Update Future Direction: Lifetime dependence for closures
+
 #### See Also
 
 * [Forum discussion of Non-Escapable Types and Lifetime Dependency](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency)
@@ -1068,18 +1071,18 @@ func g1(closure: () -> NEType) // Inferred: NEType depends on 'closure'
 ```
 
 For closure declarations, lifetime dependencies can be inferred on the combined list of captures and closure parameters
-following the same rule as free standing functions. We can infer a lifetime dependence if the closure's return value is
-nonescapable, and exactly one closure capture or closure parameter satisfies any of the following:
+following inference rules similar to those for freestanding functions:
+
+1. For closures where the return value is nonescapable, we infer a copied lifetime dependency on all captures and parameters of the same nonescapable type.
 
-  - is nonescapable, or
-  - is non-BitwiseCopyable and has an explicit `borrowing`, or `inout` convention
+2. For closures that have a nonescapable return value and a single captured value or parameter, we infer dependence on that capture or parameter. If the capture or parameter is nonescapable, then we infer a copying dependency; otherwise, we infer a scoped dependency.
 
 A dependence can be inferred on a closure capture as follows:
 
 ```swift
-func f(arg: borrowing ArgType) -> dependsOn(arg) NEType
+func f(arg: ArgType) -> dependsOn(arg) NEType
 
-func foo(source: borrowing ArgType) {
+func foo(source: ArgType) {
   g1 { f(arg: source) } // âś… Inferred: 'closure' result depends on captured 'source'
 }
 ```
@@ -1087,7 +1090,7 @@ func foo(source: borrowing ArgType) {
 An explicit dependence on a closure capture can be spelled:
 
 ```swift
-func foo(source: borrowing ArgType) {
+func foo(source: ArgType) {
   g1 { () -> dependsOn(source) NEType in f(arg: source) }
 }
 ```
@@ -1095,10 +1098,10 @@ func foo(source: borrowing ArgType) {
 Similarly, a dependence can be inferred on a closure parameter:
 
 ```swift
-func g2(closure: (borrowing ArgType) -> dependsOn(0) NEType)
+func g2(closure: (ArgType) -> dependsOn(0) NEType)
 
 {
-  g2 { (source: borrowing ArgType) in f(arg: source) } // âś… Inferred: 'closure' result depends on 'source' parameter
+  g2 { (source: ArgType) in f(arg: source) } // âś… Inferred: 'closure' result depends on 'source' parameter
 }
 ```
 
@@ -1106,7 +1109,7 @@ An explicit dependence on a closure parameter can be spelled:
 
 ```swift
 {
-  g2 { (source: borrowing ArgType) -> dependsOn(source) NEType in f(arg: source) } // âś… Inferred: 'closure' result depends on 'source' parameter
+  g2 { (source: ArgType) -> dependsOn(source) NEType in f(arg: source) }
 }
 ```
 

From 897912210b2ff94db799ffde8c9538c5e55a0a23 Mon Sep 17 00:00:00 2001
From: Joe Groff <jgroff@apple.com>
Date: Fri, 21 Mar 2025 18:13:55 -0700
Subject: [PATCH 52/59] Update proposal to match the state as of March 2025

---
 proposals/NNNN-lifetime-dependency.md | 1113 +++++++++++--------------
 1 file changed, 476 insertions(+), 637 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 08c9fa5aaf..7d9636b468 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -1,20 +1,25 @@
 # Compile-time Lifetime Dependency Annotations
 
-* Proposal: [SE-NNNN](NNNN-filename.md)
-* Authors: [Andrew Trick](https://github.com/atrick), [Meghana Gupta](https://github.com/meg-gupta), [Tim Kientzle](https://github.com/tbkka)
+* Proposal: [SE-NNNN](NNNN-lifetime-dependency.md)
+* Authors: [Andrew Trick](https://github.com/atrick), [Meghana Gupta](https://github.com/meg-gupta), [Tim Kientzle](https://github.com/tbkka), [Joe Groff](https://github.com/jckarter/)
 * Review Manager: TBD
-* Status: **Awaiting implementation**
-* Review: ([pitch](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865))
+* Status: **Implemented** in `main` branch, with the `LifetimeDependence` experimental feature flag
+* Review: ([pitch 1](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865))
 
 ## Introduction
 
-We would like to propose extensions to Swift's function-declaration syntax that allow authors to specify lifetime dependencies between the return value and one or more of the parameters.
-These would also be useable with methods that wish to declare a dependency on `self`.
-To reduce the burden of manually adding such annotations, we also propose inferring lifetime dependencies in certain common cases without requiring any additional annotations.
+We would like to propose an attribute for Swift function, initializer, method, and property accessor declarations that allow authors to specify lifetime dependencies between a declaration's return value and one or more of its parameters.
 
-This is a key requirement for the `Span` type (previously called `BufferView`) being discussed elsewhere, and is closely related to the proposal for `~Escapable` types.
+This is deeply related to `~Escapable` types, as introduced in [SE-0446](0446-non-escapable.md). This proposal exposes the underyling mechanisms used by the standard library to implement [SE-0447](0447-span-access-shared-contiguous-storage.md)'s `Span` and [SE-0467](0467-MutableSpan.md)'s `MutableSpan` types, as well as the new APIs for creating instances of these types from standard library collections added in [SE-0456](0456-stdlib-span-properties.md), providing a consistent framework by which user-defined types and functions can also express lifetime dependencies.
 
-**Edited** (Apr 12, 2024): Changed `@dependsOn` to `dependsOn` to match the current implementation.
+**Edited** (March 20, 2025):
+
+- Replaced `dependsOn` return type modifier with a declaration-level `@lifetime` attribute.
+Removed dependency inference rules.
+- Integrated links to proposals SE-0446 (`Escapable`), SE-0447 (`Span`), SE-0456 (`Span`-producing properties), and SE-0467 (`MutableSpan`) that have undergone review.
+- Added SE-0458 `@unsafe` annotations to the `unsafeLifetime` standard library functions, and added `@unsafe` as a requirement for APIs using `BitwiseCopyable` lifetime dependencies under strict memory safety.
+
+**Edited** (April 12, 2024): Changed `@dependsOn` to `dependsOn` to match the current implementation.
 
 **Edited** (May 2, 2024): Changed `StorageView` and `BufferReference` to `Span` to match the sibling proposal.
 
@@ -60,11 +65,12 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
 * [Pitch Thread for Span](https://forums.swift.org/t/pitch-safe-access-to-contiguous-storage/69888)
 * [Forum discussion of BufferView language requirements](https://forums.swift.org/t/roadmap-language-support-for-bufferview)
 * [Proposed Vision document for BufferView language requirements (includes description of ~Escapable)](https://github.com/atrick/swift-evolution/blob/fd63292839808423a5062499f588f557000c5d15/visions/language-support-for-BufferView.md#non-escaping-bufferview) 
+* [First pitch thread for lifetime dependencies](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865)
 
 ## Motivation
 
 An efficient way to provide one piece of code with temporary access to data stored in some other piece of code is with a pointer to the data in memory.
-Swift's `Unsafe*Pointer` family of types can be used here, but as the name implies, using these types can be error-prone.
+Swift's `Unsafe*Pointer` family of types can be used here, but as the name implies, using these types is not statically safe and can be error-prone.
 
 For example, suppose `ContiguousArray` had a property `unsafeBufferPointer` that returned an `UnsafeBufferPointer` to the contents of the array.
 Here's an attempt to use such a property:
@@ -76,7 +82,7 @@ parse(buff) // <== 🛑 NOT SAFE!
 ```
 
 One reason for this unsafety is because Swift's standard lifetime rules only apply to individual values.
-They cannot guarantee that `buff` will outlive the `array`, which means there is a risk that the compiler might choose to destroy `array` before the call to `parse`, which could result in `buff` referencing deallocated memory.
+They cannot guarantee that `array` will outlive `buff`, which means there is a risk that the compiler might choose to destroy `array` before the call to `parse`, which could result in `buff` referencing deallocated memory.
 (There are other reasons that this specific example is unsafe, but the lifetime issue is the one that specifically concerns us here.)
 
 Library authors trying to support this kind of code pattern today have a few options, but none are entirely satisfactory:
@@ -101,114 +107,166 @@ A "lifetime dependency" between two objects indicates that one of them can only
 This dependency is enforced entirely at compile time; it requires no run-time support.
 These lifetime dependencies can be expressed in several different ways, with varying trade-offs of expressiveness and ease-of-use.
 
-### Background: "Escapable" and “Nonescapable” Types
-
-In order to avoid changing the meaning of existing code, we will introduce a
-new protocol `Escapable` which can be suppressed with `~Escapable`.
+### Background: `Escapable` and Non-`Escapable` Types
 
+[SE-0446](0446-non-escapable.md) introduced the `Escapable` protocol for controlling lifetime dependency of types.
 Normal Swift types are `Escapable` by default.
 This implies that they can be returned, stored in properties, or otherwise "escape" the local context.
-Conversely, types can be explicitly declared to be "nonescapable" using `~Escapable`.
-These types are not allowed to escape the local context except in very specific circumstances.
-A separate proposal explains the general syntax and semantics of `Escapable` and `~Escapable`.
+Conversely, types can be suppress this implicit assumption of escapability by being declared as `~Escapable`.
+Values of types that are not known to be `Escapable` are not allowed to escape the local context except in very specific circumstances.
 
-By themselves, nonescapable types have severe constraints on usage.
-For example, consider a hypothetical `Span` type that is similar type that is being proposed for inclusion in the standard library. It simply holds a pointer and size and can be used to access data stored in a contiguous block of memory. (We are not proposing this type; it is shown here merely for illustrative purposes.)
+By themselves, non-`Escapable` types have severe constraints on usage.
+For example, consider the `Span` type from [SE-0447](0447-span-access-shared-contiguous-storage.md). It simply holds a pointer and size and can be used to access data stored in a contiguous block of memory.
 
 ```swift
-struct Span<T>: ~Escapable {
+// This is not necessarily the exact definition from the standard library, but
+// is close enough to serve as an example.
+public struct Span<T>: ~Escapable {
   private var base: UnsafePointer<T>
   private var count: Int
 }
 ```
 
-Because this type is marked as unconditionally `~Escapable`, it cannot be returned from a function or even initialized without some way to relax the escapability restrictions.
-This proposal provides a set of constraints that can tie the lifetime of a nonescapable value to the lifetime of some other value.
-In the most common cases, these constraints can be inferred automatically.
-
-### Explicit Lifetime Dependency Annotations
+Because the `Span` type is marked as unconditionally `~Escapable`, it cannot be returned from a function or even initialized without some way to relax the escapability restrictions.
+[SE-0456](0456-stdlib-span-properties.md) imbued `span` accessors on certain standard library types with specific lifetime relationships that allowed for only those accessors to return `Span` instances, and [SE-0467](0467-MutableSpan.md) subsequently did the same for `mutableSpan` accessors on those same types.
+This proposal supersedes those special cases with a general-purpose mechanism for providing a set of constraints that can tie the lifetime of a non-`Escapable` value to the lifetime of other values.
 
-To make the semantics clearer, we’ll begin by describing how one can explicitly specify a lifetime constraint in cases where the default inference rules do not apply.
+### Lifetime Dependency Annotations
 
-Let’s consider adding support for our hypothetical `Span` type to `ContiguousArray`.
-Our proposal would allow you to declare an `array.span()` method as follows:
+Let's consider adding support for our hypothetical `Span` type to `ContiguousArray`.
+Our proposal will allow you to declare an `array.span` property as follows:
 
 ```swift
 extension ContiguousArray {
-  borrowing func span() -> dependsOn(self) Span<Element> {
-    ... construct a Span ...
+  var span: Span<Element> {
+    @lifetime(borrow self)
+    borrowing get {
+        ... construct a Span ...
+    }
   }
 }
 ```
 
-The annotation `dependsOn(self)` here indicates that the returned value must not outlive the array that produced it.
-Conceptually, it is a continuation of the function's borrowing access:
-the array is being borrowed by the function while the function executes and then continues to be borrowed by the `Span` for as long as the return value exists.
-Specifically, the `dependsOn(self)` annotation in this example informs the compiler that:
+The annotation `@lifetime(borrow self)` here indicates that the returned value must not outlive the array that produced it.
+Futhermore, the originating array value behaves as if it is borrowed for the duration of the `span`'s lifetime, meaning not only that the array cannot be destroyed, but also cannot be modified while the `span` is alive.
+Conceptually, the `span` acts as a continuation of the function's borrowing access:
+the array is borrowed by the function while the function executes and then continues to be borrowed by the result of `span` for as long as the return value exists.
+Specifically, the `@lifetime(borrow self)` annotation in this example informs the compiler that:
 
 * The array must not be destroyed until after the `Span<Element>` is destroyed.
   This ensures that use-after-free cannot occur.
 * The array must not be mutated while the  `Span<Element>` value exists.
-  This follows the usual Swift exclusivity rules for a borrowing access.
+  This follows the usual Swift exclusivity rules for mutation; mutation requires exclusive access, so cannot occur during a borrowing access.
+  However, just like a variable can undergo multiple simultaneous borrowing accesses, so can multiple `Span`s depend on borrowing the same origin `array`.
+  In this case, the `array` is borrowed until the end of the lifetimes of all of its borrow-dependent values.
 
 #### Scoped Lifetime Dependency
 
-Let’s consider another hypothetical type: a `MutatingSpan<T>` type that could provide indirect mutating access to a block of memory.
-Here's one way such a value might be produced:
+Let's now consider the `MutableSpan<T>` type from [SE-0467](0467-MutableSpan.md), which provides indirect mutating access to a block of memory.
+Here's one way such a value might be produced from an owning array:
 
 ```swift
-func mutatingSpan(to: inout ContiguousArray, count: Int) -> dependsOn(to) MutatingSpan<Element> {
+@lifetime(inout to)
+func mutatingSpan<Element>(to: inout ContiguousArray<Element>, count: Int) -> MutatingSpan<Element> {
   ... construct a MutatingSpan ...
 }
 ```
 
-We’ve written this example as a free function rather than as a method to show how this annotation syntax can be used to express constraints that apply to a particular argument.
-The `dependsOn(to)` annotation indicates that the returned value depends on the argument named `to`.
+We’ve written this example as a free function rather than as a method to show how this annotation syntax can be used to express constraints that apply to a particular parameter other than `self`.
+The `@lifetime(inout to)` annotation indicates that the returned value depends on the argument named `to`.
 Because `count` is not mentioned in the lifetime dependency, that argument does not participate.
+Instead of `borrow`, this annotation uses the `inout` keyword to indicate that the returned span depends on **mutating** exclusive access to the `to` parameter rather than borrowed access.
+
 Similar to the previous example:
 
-* The array will not be destroyed until after the `MutatingSpan<Element>` is destroyed.
-* No other read or write access to the array will be allowed for as long as the returned value exists.
+* The array will not be destroyed until after the `MutableSpan<Element>` is destroyed.
+
+However, by contrast with the previous `borrow` dependency:
+
+* No other read or write access to the array will be allowed for as long as the returned value exists, since the dependency requires exclusivity.
 
-In both this and the previous case, the lifetime of the return value is "scoped" to the lifetime of the original value.
-Because lifetime dependencies can only be attached to nonescapable values, types that contain pointers will generally need to be nonescapable in order to provide safe semantics.
-As a result, **scoped lifetime dependencies** are the only possibility whenever an `Escapable` value (such as a ContiguousArray or similar container) is providing a nonescapable value (such as the `Span` or `MutatingSpan` in these examples).
+In both the `inout` and the `borrow` dependency case, the lifetime of the return value is "scoped" to an access into the lifetime of the original value.
+Because lifetime dependencies can only be attached to non-`Escapable` values, types that contain pointers will generally need to be non-`Escapable` in order to provide safe semantics.
+As a result, **scoped lifetime dependencies** are the only possibility whenever a non-`Escapable` value (such as `Span` or `MutableSpan`) gets its dependency from an `Escapable` value (such as `ContiguousArray` or similar container).
 
 #### Copied Lifetime Dependency
 
-The case where a nonescapable value is used to produce another nonescapable value is somewhat different.
-Here's a typical example that constructs a new `Span` from an existing one:
+A non-`Escapable` value can also derive its dependency from another non-`Escapable` value, but this case is somewhat different.
+For instance, `Span` has an `extracting` method that returns another `Span` referring to a subrange of the same memory referenced by the original `Span`.
+This method can be declared as follows:
+
 ```swift
 struct Span<T>: ~Escapable {
-  ...
-  consuming func drop(_: Int) -> dependsOn(self) Span<T> { ... }
-  ...
+    @lifetime(copy self)
+    func extracting(_ range: Range<Int>) -> Span<T> {
+        ...make derived span...
+    }
 }
 ```
 
-In this examples, the nonescapable result depends on a nonescapable value.
-Recall that nonescapable values such as these represent values that are already lifetime-constrained to another value.
+In this example, the non-`Escapable` result doesn't depend on the first non-`Escapable` value that it was derived from.
+Recall that non-`Escapable` values such as these represent values that are already lifetime-constrained to another value; in this case, the returned `Span` is ultimately dependent on the same owning value as the original `Span`.
 
-For a `consuming` method, the return value cannot have a scoped lifetime dependency on the original value, since the original value no longer exists when the method returns.
-Instead, the return value must "copy" the lifetime dependency from the original:
+To express this, the return value can "copy" the lifetime dependency from the original:
 If the original `Span` was borrowing some array, the new `Span` will continue to borrow the same array.
 
 This supports coding patterns such as this:
 ```swift
-let a: ContiguousArray<Int>
-let ref1 = a.span() // ref1 cannot outlive a
-let ref2 = ref1.drop(4) // ref2 also cannot outlive a
+var a: ContiguousArray<Int>
+let ref1 = a.span // ref1 cannot outlive a
+let ref2 = ref1.extracting(4 ..< ref1.count) // ref2 also cannot outlive a
+```
+
+After `ref1.extracting(4 ..< ref1.count)`, the lifetime of `ref2` does not depend on `ref1`.
+The `extracting` method **copies** `ref1`s lifetime depenence onto `ref2`.
+`ref2` effectively **inherits** the same lifetime dependency on `a` as `ref1`.
+We may also refer to a lifetime dependence that has been copied from another value as an "inherited" dependence.
+Since both `ref1` and `ref2` have borrowing scoped dependencies on `a`, they can be used simultaneously:
+
+```
+print(ref1[0])
+print(ref2[0])
+```
+
+`ref2` can continue to be used after the end of `ref1`'s lifetime, as long as `a` remains valid:
+
+```
+_ = consume ref1 // explicitly end ref1's lifetime here
+print(ref2[0]) // OK, ref2 is still valid
+
+_ = consume a // explicitly end a's lifetime here
+print(ref2[0]) // error: ref2 cannot exceed a's lifetime
+```
+
+`a` cannot be mutated or destroyed until both `ref1` and `ref2` have expired:
+
+```
+a.append(1) // error: 'a' is borrowed by 'ref1' and 'ref2'
+_ = consume ref2
+a.append(1) // error: 'a' is borrowed by 'ref1'
+_ = consume ref1
+a.append(1) // OK
+```
+
+Note that non-`Escapable` values can still have scoped dependencies on other non-`Escapable` values as well.
+This comes up frequently with `MutableSpan` due to its interaction with exclusivity.
+Since there can only be one mutating reference to a mutable value at any time, `MutableSpan`'s version of the `extracting` method must pass off that responsibility to the extracted `MutableSpan` for the latter value's lifetime and prevent overlapping access through the base `MutableSpan` until the extracted `MutableSpan` is no longer usable. It can achieve this by giving the extracted `MutableSpan` a scoped dependency:
+
+```
+extension MutableSpan {
+  @lifetime(inout self)
+  mutating func extracting(_ range: Range<Int>) -> MutableSpan<Element> {
+    ...
+  }
+}
 ```
 
-After `ref1.drop(4)`, the lifetime of `ref2` does not depend on `ref1`, which is consumed within the method. Instead,
-the `drop` method **copies** `ref1`s lifetime depenence onto `ref2`. `ref2` effectively **inherits** a lifetime
-dependency on `a`. We may refer to a lifetime dependence that has been copied from another value as an "inherited"
-dependence.
+Since the return value of `extracting` has a scoped `inout` dependency on the original `MutableSpan`, the original cannot be accessed while the new value is active.
+When the extracted `MutableSpan` ends its lifetime, the exclusive access to the original ends, making it available for use again, thereby allowing for the derivation of new `MutableSpan`s without violating exclusivity.
 
-#### Allowed Lifetime Dependencies
+### Allowed Lifetime Dependencies
 
-The previous sections described **scoped lifetime dependencies** and **copied lifetime dependencies**
-and showed how each type occurs naturally in different use cases.
+The previous sections described **scoped lifetime dependencies** and **copied lifetime dependencies** and showed how each type occurs naturally in different use cases.
 
 Now let's look at the full range of possibilities for explicit constraints.
 The syntax is somewhat different for functions and methods, though the basic rules are essentially the same.
@@ -216,191 +274,148 @@ The syntax is somewhat different for functions and methods, though the basic rul
 **Functions:** A simple function with an explicit lifetime dependency annotation generally takes this form:
 
 ```swift
-func f(arg: <parameter-convention> ArgType) -> dependsOn(arg) ResultType
+@lifetime(<dependency-kind> arg)
+func f(arg: ArgType) -> ResultType
 ```
 
 Where
 
-*  *`parameter-convention`* is one of the ownership specifiers **`borrowing`**, **`consuming`**, or **`inout`**, (this may be implied by Swift’s default parameter ownership rules),
-* `ResultType` must be nonescapable.
+*  *`dependency-kind`* is one of the dependency specifiers **`borrow`**, **`inout`**, or **`copy`**, and
+* `ResultType` must be non-`Escapable`.
 
-If the `ArgType` is escapable, the return value will have a new scoped dependency on the argument.
-(This is the only possibility, as an escapable value cannot have an existing lifetime dependency,
-so we cannot copy the lifetime dependency.)
-A scoped dependency ensures the argument will not be destroyed while the result is alive.
+If the `ArgType` is `Escapable`, the dependency specifier must be `borrow` or `inout` and return value will have a new scoped dependency on the argument.
+(This is the only possibility, since an `Escapable` value cannot have an existing lifetime dependency, so we cannot copy its lifetime dependency.)
+The specifier must further correspond to the ownership of `arg`: if `arg` has no ownership specified, or is explicitly `borrowing`, then the dependency must be `borrow`.
+On the other hand, if `arg` is `inout`, the dependency must also be `inout`.
+(A scoped dependency cannot be formed on a `consuming` parameter.)
+
+A scoped dependency ensures that the argument will not be destroyed while the result is alive.
 Also, access to the argument will be restricted for the lifetime of the result following Swift's usual exclusivity rules:
 
-* A `borrowing` parameter-convention extends borrowing access, prohibiting mutations of the argument.
-* An `inout` parameter-convention extends mutating access, prohibiting any access to the argument.
+* A `borrowing` parameter-convention extends borrowing access, prohibiting mutations of the argument, but allowing other simultaneous borrowing accesses.
+* An `inout` parameter-convention extends mutating access, prohibiting any other access to the argument f, whether borrowing or mutating.
 * A `consuming` parameter-convention is illegal, since that ends the lifetime of the argument immediately.
 
-If the `ArgType` is nonescapable, then it can have a pre-existing lifetime dependency.
-In this case, the semantics of `dependsOn()` are slightly different:
-* A `consuming` parameter-convention will copy the lifetime dependency from the argument to the result
-* A `borrowing` or `inout` parameter-convention can either copy the lifetime dependency or create a new scoped lifetime dependency.
-  In this case, for reasons explained earlier, we default to copying the lifetime dependency.
-  If a scoped lifetime dependency is needed, it can be explicitly requested by adding the `scoped` keyword:
-  
-```swift
-func f(arg: borrowing ArgType) -> dependsOn(scoped arg) ResultType
-```
+If the `ArgType` is non-`Escapable`, then it can have a pre-existing lifetime dependency.
+In this case, in addition to `borrow` or `inout`, a `copy` dependency-kind is allowed, to indicate that the returned value has the same dependency as the argument.
+`borrow` and `inout` dependency kinds continue to work as for `Escapable` types, and indicate that the returned value has a scoped lifetime dependency based on an access to the argument, making the returned value even further lifetime-constrained than the argument going in.
 
-**Methods:** Similar rules apply to `self` lifetime dependencies on methods.
+**Methods:** Similar rules apply to lifetime dependencies on `self` in methods.
 Given a method of this form:
 
 ```swift
-<mutation-modifier> func method(... args ...) -> dependsOn(self) ResultType
+@lifetime(<dependency-kind> self)
+<mutation-modifier> func method(... args ...) -> ResultType
 ```
 
-The behavior depends as above on the mutation-modifier and whether the defining type is escapable or nonescapable.
+The behavior depends as above on the dependency-kind and whether the defining type is `Escapable`.
+For a method of an `Escapable` type, the dependency-kind must be `borrow self` for a `borrowing` method, or `inout self` for a `mutating` method, and lifetime dependencies are not allowed on `self` in a `consuming` method.
+For a method of a non-`Escapable` type, the dependency-kind may additionally be `copy self`.
 
-**Initializers:** An initializer can define lifetime dependencies on one or more arguments.
+**Initializers:** An initializer can also define lifetime dependencies on one or more arguments.
 In this case, we use the same rules as for “Functions” above
 by using the convention that initializers can be viewed as functions that return `Self`:
 
 ```swift
-init(arg: <parameter-convention> ArgType) -> dependsOn(arg) Self
+@lifetime(<dependency-kind> arg)
+init(arg: ArgType)
 ```
 
-### Implicit Lifetime Dependencies
+#### Dependent Parameters
 
-The syntax above allows developers to explicitly annotate lifetime dependencies in their code.  But because the possibilities are limited, we can usually allow the compiler to infer a suitable dependency.  The detailed rules are below, but generally we require that the return type be nonescapable and that there be an “obvious” source for the dependency.
-
-#### Self dependence
-
-We can infer a lifetime dependency on `self` for any method that returns a nonescapable value. As above, the details vary depending on whether `self` is escapable or nonescapable:
-
-```swift
-struct NonescapableType: ~Escapable { ... }
-struct EscStruct {
-  func f1(...) -> /* dependsOn(self) */ NonescapableType
-  borrowing func f2(...) -> /* dependsOn(self) */ NonescapableType
-  mutating func f3(...) -> /* dependsOn(self) */ NonescapableType
-
-  // 🛑 Error: there is no valid lifetime dependency for
-  // a consuming method on an `Escapable` type
-  consuming func f4(...) -> NonescapableType
-}
-
-struct NEStruct: ~Escapable {
-  func f1(...) -> /* dependsOn(self) */ NonescapableType
-  borrowing func f2(...) -> /* dependsOn(self) */ NonescapableType
-  mutating func f3(...) -> /* dependsOn(self) */ NonescapableType
-
-  // Note: A copied lifetime dependency is legal here
-  consuming func f4(...) -> /* dependsOn(self) */ NonescapableType
-}
-```
-
-#### Same-type dependence
-
-For any function or method that returns a nonescapable type, we infer a copied lifetime dependency on all parameters of the same type.
-
-`func foo<T: ~Escapable, U: ~Escapable, R: ~Escapable>(x: T, y: U) -> R { ... }`
-
-implies:
-
-```
--> dependsOn(x) where R == T
--> dependsOn(y) where R == U
--> dependsOn(x, y) where R == T == U
-```
-
-This is particularly helpful for Generic APIs. With this rule, indicating that a generic parameter is `~Escapable` should usually be sufficient to infer the correct lifetime dependence.
-
-For methods, if `self` is the same type as the result, the same-type rule also applies, resulting in a copied dependence on `self`. This case overlaps with the aforementioned self dependence rule above and has the same effect.
-
-### Dependent parameters
-
-Normally, lifetime dependence is required when a nonescapable function result depends on an argument to that function. In some rare cases, however, a nonescapable function parameter may depend on another argument to that function. Consider a function with an `inout` parameter. The function body may reassign that parameter to a value that depends on another parameter. This is similar in principle to a result dependence.
+Normally, lifetime dependence is required when a non-`Escapable` function result depends on an argument to that function. However, `inout` parameters of non-`Escapable` type also express an operation that results in a new non-`Escapable` value as a result of mutation by calling the function, so that function parameter may also depend on another argument to a function call. The target of a dependency can be expressed before a colon in a `@lifetime` attribute:
 
 ```swift
-func mayReassign(span: dependsOn(a) inout Span<Int>, to a: ContiguousArray<Int>) {
-  span = a.span()
+@lifetime(span: borrow a)
+func mayReassign(span: inout Span<Int>, to a: ContiguousArray<Int>) {
+  span = a.span
 }
 ```
 
-The `dependsOn(self:)` keyword is required to indicate that a method's implicit `self` depends on another parameter.
+`@lifetime(self:)` can also be used to indicate that a `mutating` method's implicit `self` depends on another parameter after being mutated.
 
 ```swift
 extension Span {
-  mutating dependsOn(self: other) func reassign(other: Span<T>) {
-    self = other // âś… OK: 'self' depends on 'other'
+  @lifetime(self: copy other)
+  mutating func reassign(other: Span<T>) {
+    self = other
   }
 }
 ```
 
-We've discussed how a nonescapable result must be destroyed before the source of its lifetime dependence. Similarly, a dependent argument must be destroyed before an argument that it depends on. The difference is that the dependent argument may already have a lifetime dependence when it enters the function. The new function argument dependence is additive, because the call does not guarantee reassignment. Instead, passing the 'inout' argument is like a conditional reassignment. After the function call, the dependent argument carries both lifetime dependencies.
+We've discussed how a non-`Escapable` result must be destroyed before the source of its lifetime dependence. Similarly, a dependent argument must be destroyed before an argument that it depends on. The difference is that the dependent argument may already have a lifetime dependence when it enters the function. The new function argument dependence is additive, because the call does not guarantee reassignment. Instead, passing the 'inout' argument is like a conditional reassignment. After the function call, the dependent argument carries both lifetime dependencies.
 
 ```swift
   let a1: ContiguousArray<Int> = ...
-  var span = a1.span()
+  var span = a1.span
   let a2: ContiguousArray<Int> = ...
   mayReassign(span: &span, to: a2)
   // 'span' now depends on both 'a1' and 'a2'.
 ```
 
-The general form of the `dependsOn` syntax is:
-
-> **dependsOn**(*target*: *source*)
-
-where `target` can be inferred from context:
-
-- Result modifiers go before the result type (after the `->` sigil)
-
-- Parameter modifiers go before the parameter type
-
-- `self` modifiers always go in front of the `func` declaration.
-
-Although `self` could be inferred, it must be spelled explicitly to avoid confusion with the common case of a result
-dependence.
-
-Example:
+The general form of a `@lifetime` attribute is:
 
+```swift
+@lifetime(target: <dependency-kind> source)
 ```
-  dependsOn(self: arg1) func foo<T, R>(arg1: dependsOn(arg2) T, arg2: T) -> dependsOn(arg2) R
-```
 
-### Dependent properties
+where `target` can be elided to refer to the return value of the declaration.
+
+#### Dependent properties
 
-Structural composition is an important use case for nonescapable types. Getting or setting a nonescapable property requires lifetime dependence, just like a function result or an 'inout' parameter. There's no need for explicit annotation in these cases, because only one dependence is possible. A getter returns a value that depends on `self`. A setter replaces the current dependence from `self` with a dependence on `newValue`.
+Structural composition is an important use case for non-`Escapable` types. Getting or setting a non-`Escapable` computed property requires lifetime dependence, just like a function result or an 'inout' parameter:
 
 ```swift
 struct Container<Element>: ~Escapable {
   var element: Element {
-    get /* dependsOn(self) */ { ... }
-    /* dependsOn(self: newValue) */ set { ... }
+    @lifetime(copy self)
+    get { ... }
+
+    @lifetime(self: copy newValue)
+    set { ... }
   }
 
-  init(element: Element) /* -> dependsOn(element) Self */ {...}
+  @lifetime(copy element)
+  init(element: Element) { ... }
 }
 ```
 
-### Conditional dependencies
+### Conditional lifetime dependencies
 
-Conditionally nonescapable types can contain nonescapable elements:
+Conditionally non-`Escapable` types can also contain potentially non-`Escapable` elements:
 
 ```swift
-    struct Container<Element>: ~Escapable {
-      var element: /* dependsOn(self) */ Element
+struct Container<Element: ~Escapable>: ~Escapable {
+  var element: Element
 
-      init(element: Element) -> dependsOn(element) Self {...}
+  @lifetime(copy element)
+  init(element: Element) { self.element = element }
 
-      func getElement() -> dependsOn(self) Element { element }
-    }
+  @lifetime(copy self)
+  func getElement() -> Element { element }
+}
 
-    extension Container<E> { // OK: conforms to Escapable.
-      // Escapable context...
-    }
+extension Container: Escapable where Element: Escapable { }
+}
 ```
 
-Here, `Container` becomes nonescapable only when its element type is nonescapable. When `Container` is nonescapable, it inherits the lifetime of its single element value from the initializer and propagates that lifetime to all uses of its `element` property or the `getElement()` function.
+Here, `Container` is non-`Escapable` only when its element type is non-`Escapable`. Whenever `Container` is potentially non-`Escapable`, it inherits the lifetime of the single `element` argument to the initializer and propagates that lifetime to all uses of its `element` property or the `getElement()` function.
+
+In some contexts, however, the `Element` is known to conform to `Escapable`, which in turn makes `Container<Element>` for that `Element` type `Escapable`. When generic substitution produces an `Escapable` type, any `@lifetime` dependencies applied to that type are ignored.
 
-In some contexts, however, `Container` and `Element` both conform to `Escapable`. In those contexts, any `dependsOn` in `Container`'s interface is ignored, whether explicitly annotated or implied. So, when `Container`'s element conforms to `Escapable`, the `-> dependsOn(element) Self` annotation in its initializer is ignored, and the `-> dependsOn(self) Element` in `getElement()` is ignored.
+```
+let s = "strings are immortal"
+var s2: String
+do {
+    let c = Container<String>(element: s)
+    s2 = c.getElement()
+}
+print(s2) // OK, String is Escapable, so it isn't affected by the lifetime dependency
+```
 
 ### Immortal lifetimes
 
-In some cases, a nonescapable value must be constructed without any object that can stand in as the source of a dependence. Consider extending the standard library `Optional` or `Result` types to be conditionally escapable:
+In some cases, a non-`Escapable` value must be constructed without any object that can stand in as the source of a dependence. Consider the standard library `Optional` or `Result` types, which became conditionally `Escapable` in [SE-0465](0465-nonescapable-stdlib-primitives.md):
 
 ```swift
 enum Optional<Wrapped: ~Escapable>: ~Escapable {
@@ -416,11 +431,12 @@ enum Result<Success: ~Escapable, Failure: Error>: ~Escapable {
 extension Result: Escapable where Success: Escapable {}
 ```
 
-When constructing an `Optional<NotEscapable>.none` or `Result<NotEscapable>.failure(error)` case, there's no lifetime to assign to the constructed value in isolation, and it wouldn't necessarily need one for safety purposes, because the given instance of the value doesn't store any state with a lifetime dependency. Instead, the initializer for cases like this can be annotated with `dependsOn(immortal)`:
+When constructing an `Optional<NotEscapable>.none` or `Result<NotEscapable>.failure(error)` case, there's no lifetime to assign to the constructed value in isolation, and it wouldn't necessarily need one for safety purposes, because the given instance of the value doesn't store any state with a lifetime dependency. Instead, the initializer for cases like this can be annotated with `@lifetime(immortal)`:
 
 ```swift
-extension Optional {
-  init(nilLiteral: ()) dependsOn(immortal) {
+extension Optional where Wrapped: ~Escapable {
+  @lifetime(immortal)
+  init(nilLiteral: ()) {
     self = .none
   }
 }
@@ -428,37 +444,40 @@ extension Optional {
 
 The constructed instance is returned to the caller without any lifetime dependence. The caller can pass that instance
 along as an argument to other functions, but those functions cannot escape it. The instance can only be returned further
-up the call stack by chaining multiple `dependsOn(immortal)` functions.
+up the call stack by chaining multiple `@lifetime(immortal)` functions.
 
 #### Depending on immutable global variables
 
-Another place where immortal lifetimes might come up is with dependencies on global variables. When a value has a scoped dependency on a global let constant, that constant lives for the duration of the process and is effectively perpetually borrowed, so one could say that values dependent on such a constant have an effectively infinite lifetime as well. This will allow returning a value that depends on a global by declaring the function's return type with `dependsOn(immortal)`:
+Another place where immortal lifetimes might come up is with dependencies on global variables. When a value has a scoped dependency on a global let constant, that constant lives for the duration of the process and is effectively perpetually borrowed, so one could say that values dependent on such a constant have an effectively infinite lifetime as well. This will allow returning a value that depends on a global by declaring the function's return type with `@lifetime(immortal)`:
 
 ```swift
 let staticBuffer = ...
 
-func getStaticallyAllocated() -> dependsOn(immortal) BufferReference {
+@lifetime(immortal)
+func getStaticallyAllocated() -> BufferReference {
   staticBuffer.bufferReference()
 }
 ```
 
 #### Immortal requirements
 
-`dependsOn(immortal)` requires the programmer to compose the dependent value from something that, in fact, has an immortal lifetime:
+`@lifetime(immortal)` requires the programmer to compose the dependent value from something that, in fact, has an immortal lifetime:
 
 ```swift
-init() dependsOn(immortal) {
+@lifetime(immortal)
+init() {
   self.value = <global constant>
 }
 ```
 
 `<global constant>` must be valid over the entire program.
 
-`dependsOn(immortal)` is not a way to suppress dependence in cases where the source value has unknown
+`@lifetime(immortal)` is not a way to suppress dependence in cases where the source value has unknown
 lifetime. Composing the result from a transient value, such as an UnsafePointer, is incorrect:
 
 ```swift
-init(pointer: UnsafePointer<T>) dependsOn(immortal) {
+@lifetime(immortal)
+init(pointer: UnsafePointer<T>) {
   self.value = pointer // 🛑 Incorrect
 }
 ```
@@ -466,25 +485,28 @@ init(pointer: UnsafePointer<T>) dependsOn(immortal) {
 We could run into the same problem with any transient value, like a file descriptor, or even a class object:
 
 ```swift
-init() dependsOn(immortal) {
+@lifetime(immortal)
+init() {
   self.value = Object() // 🛑 Incorrect
 }
 ```
 
 ### Depending on an escapable `BitwiseCopyable` value
 
-The source of a lifetime depenence may be an escapable `BitwiseCopyable` value. This is useful in the implementation of data types that internally use `UnsafePointer`:
+The source of a lifetime dependence may be an escapable `BitwiseCopyable` value. This is useful in the implementation of data types that internally use `UnsafePointer`:
 
 ```swift
 struct Span<T>: ~Escapable {
   ...
   // The caller must ensure that `unsafeBaseAddress` is valid over all uses of the result.
-  init(unsafeBaseAddress: UnsafePointer<T>, count: Int) dependsOn(unsafeBaseAddress) { ... }
+  @unsafe
+  @lifetime(borrow unsafeBaseAddress)
+  init(unsafeBaseAddress: UnsafePointer<T>, count: Int) { ... }
   ...
 }
 ```
 
-By convention, when the source of a dependence is escapable and `BitwiseCopyable`, it should have an "unsafe" label, such as `unsafeBaseAddress` above. This communicates to anyone who calls the function, that they are reponsibile for ensuring that the value that the result depends on is valid over all uses of the result. The compiler can't guarantee safety because `BitwiseCopyable` types do not have a formal point at which the value is destroyed. Specifically, for `UnsafePointer`, the compiler does not know which object owns the pointed-to storage.
+When the source of a dependence is escapable and `BitwiseCopyable`, then the operation must be marked as `@unsafe` when using strict memory safety as introduced in [SE-0458](0458-strict-memory-safety.md). By convention, the argument label should also include the word `unsafe` in its name, as in `unsafeBaseAddress` above. This communicates to anyone who calls the function that they are reponsible for ensuring that the value that the result depends on is valid over all uses of the result. The compiler can't guarantee safety because `BitwiseCopyable` types do not have a formal point at which the value is destroyed. Specifically, for `UnsafePointer`, the compiler does not know which object owns the pointed-to storage.
 
 ```swift
 var span: Span<T>?
@@ -518,12 +540,6 @@ storage.withUnsafeBufferPointer { buffer in
 
 ### Standard library extensions
 
-#### Conditionally nonescapable types
-
-The following standard library types will become conditionally nonescapable: `Optional`, `ExpressibleByNilLiteral`, and `Result`.
-
-`MemoryLayout` will suppress the escapable constraint on its generic parameter.
-
 #### `unsafeLifetime` helper functions
 
 The following two helper functions will be added for implementing low-level data types:
@@ -532,25 +548,27 @@ The following two helper functions will be added for implementing low-level data
 /// Replace the current lifetime dependency of `dependent` with a new copied lifetime dependency on `source`.
 ///
 /// Precondition: `dependent` has an independent copy of the dependent state captured by `source`.
+@unsafe @lifetime(copy source)
 func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
   dependent: consuming T, dependsOn source: borrowing U)
-  -> dependsOn(source) T { ... }
+  -> T { ... }
 
 /// Replace the current lifetime dependency of `dependent` with a new scoped lifetime dependency on `source`.
 ///
 /// Precondition: `dependent` depends on state that remains valid until either:
 /// (a) `source` is either destroyed if it is immutable,
 /// or (b) exclusive to `source` access ends if it is a mutable variable.
+@unsafe @lifetime(borrowing source)
 func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
   dependent: consuming T, scoped source: borrowing U)
-  -> dependsOn(scoped source) T {...}
+  -> T {...}
 ```
 
-These are useful for nonescapable data types that are internally represented using escapable types such as `UnsafePointer`. For example, some methods on `Span` will need to derive a new `Span` object that copies the lifetime dependence of `self`:
+These are useful for non-`Escapable` data types that are internally represented using `Escapable` types such as `UnsafePointer`. For example, some methods on `Span` will need to derive a new `Span` object that copies the lifetime dependence of `self`:
 
 ```swift
 extension Span {
-  consuming func dropFirst() -> Span<T> {
+  consuming func dropFirst() -> Span<Element> {
     let local = Span(base: self.base + 1, count: self.count - 1)
     // 'local' can persist after 'self' is destroyed.
     return unsafeLifetime(dependent: local, dependsOn: self)
@@ -558,12 +576,13 @@ extension Span {
 }
 ```
 
-Since `self.base` is an escapable value, it does not propagate the lifetime dependence of its container. Without the call to `unsafeLifetime`, `local` would be limited to the local scope of the value retrieved from `self.base`, and could not be returned from the method. In this example, `unsafeLifetime` communicates that all of the dependent state from `self` has been *copied* into `local`, and, therefore, `local` can persist after `self` is destroyed.
+Since `self.base` is an `Escapable` value, it does not propagate the lifetime dependence of its container. Without the call to `unsafeLifetime`, `local` would be limited to the local scope of the value retrieved from `self.base`, and could not be returned from the method. In this example, `unsafeLifetime` communicates that all of the dependent state from `self` has been *copied* into `local`, and, therefore, `local` can persist after `self` is destroyed.
 
 `unsafeLifetime` can also be used to construct an immortal value where the compiler cannot prove immortality by passing a `Void` value as the source of the dependence:
 
 ```swift
-init() dependsOn(immortal) {
+@lifetime(immortal)
+init() {
   self.value = getGlobalConstant() // OK: unchecked dependence.
   self = unsafeLifetime(dependent: self, dependsOn: ())
 }
@@ -571,11 +590,11 @@ init() dependsOn(immortal) {
 
 ## Detailed design
 
-### Relation to ~Escapable
+### Relation to `Escapable`
 
-The lifetime dependencies described in this document can be applied only to nonescapable return values.
-Further, any return value that is nonescapable must have a lifetime dependency.
-In particular, this implies that the initializer for a nonescapable type must have at least one argument.
+The lifetime dependencies described in this document can be applied only to potentially non-`Escapable` return values.
+Further, any return value that is non-`Escapable` must declare a lifetime dependency.
+In particular, this implies that the initializer for a non-`Escapable` type must have at least one argument or else specify `@lifetime(immortal)`.
 
 ```swift
 struct S: ~Escapable {
@@ -583,12 +602,49 @@ struct S: ~Escapable {
 }
 ```
 
+In generic contexts, `~Escapable` indicates that a type is *not required* to be `Escapable`, but is *not* a strict indication that a type is not `Escapable` at all.
+Generic types can be conditionally `Escapable`, and type parameters to generic functions that are declared `~Escapable` can be given `Escapable` types as arguments.
+This proposal refers to types in these situations as "potentially non-`Escapable`" types.
+Return types that are potentially non-`Escapable` require lifetime dependencies to be specified, but when they are used in contexts where a value becomes `Escapable` due to the type parameters used, then those lifetime dependencies lose their effect, since
+
+```swift
+// `Optional` is `Escapable` only when its `Wrapped` type is `Escapable`, and
+// is not `Escapable` when its `Wrapped` type is not.
+//
+// In a generic function like `optionalize` below, `T?` is potentially
+// non-`Escapable`, so we must declare its lifetime dependency.
+@lifetime(copy value)
+func optionalize<T: ~Escapable>(_ value: T) -> T? {
+    return value
+}
+
+// When used with non-Escapable types, `optionalize`'s dependencies are imposed
+var maybeSpan: Span<Int>? = nil
+do {
+  let a: ContiguousArray<Int> = ...
+  
+  maybeSpan = optionalize(a.span)
+  // maybeSpan is now dependent on borrowing `a`, copying the dependency from
+  // `a.span` through `optionalize`
+}
+print(maybeSpan?[0]) // error, `maybeSpan` used outside of lifetime constraint
+
+// But when used with Escapable types, the dependencies lose their effect
+var maybeString: String? = 0
+do {
+    let s = "strings are eternal"
+    maybeString = optionalize(s)
+}
+print(maybeString) // OK, String? is `Escapable`, no lifetime constraint
+
+```
+
 ### Basic Semantics
 
 A lifetime dependency annotation creates a *lifetime dependency* between a *dependent value* and a *source value*.
 This relationship obeys the following requirements:
 
-* The dependent value must be nonescapable.
+* The dependent value must be potentially non-`Escapable`.
 
 * The dependent value's lifetime must not be longer than that of the source value.
 
@@ -600,126 +656,47 @@ The compiler must issue a diagnostic if any of the above cannot be satisfied.
 
 ### Grammar
 
-This new syntax adds an optional `dependsOn(...)` lifetime modifier just before the return type and parameter types. This modifies *function-result* in the Swift grammar as follows:
+This new syntax adds a `@lifetime` attribute that can be applied to function, initializer, and property accessor declarations:
 
-> *function-signature* → *parameter-clause* **`async`***?* **`throws`***?* *function-result**?* \
-> *function-signature* → *parameter-clause* **`async`***?* **`rethrows`** *function-result**?* \
-> *function-result* → **`->`** *attributes?* *lifetime-modifiers?* *type* \
-> *lifetime-modifiers* → *lifetime-modifier* *lifetime-modifiers?* \
-> *lifetime-modifier* → **`dependsOn`** **`(`** *lifetime-dependent-list* **`)`** \
-> *lifetime-dependence-list* → *lifetime-dependence-source* **`,`** *lifetime-dependent-list*
-> *lifetime-dependence-source* → **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name* | **`immortal`**
+> *lifetime-attribute* → **`@`** **`lifetime`** **`(`** *lifetime-dependence-list* **`)`**
 >
-> *parameter-type-annotation* → : *attributes?* *lifetime-modifiers?* *parameter-modifier*? *type*
+> *lifetime-dependence-list* → (*lifetime-dependence-target-name* **`:`**)? *lifetime-dependence-source* **`,`** *lifetime-dependent-list* **`,`**?
 >
-
-The new syntax also adds an optional `dependsOn(self:...)` lifetime modifier before function declarations. This extends *declaration-modifier* as follows:
-
+> *lifetime-dependence-source* → **`immortal`** | *dependency-kind* *lifetime-dependence-source-name*
 >
-> *declaration-modifier* → **`dependsOn`** **`(`** **`self`** **`:`** *lifetime-dependent-list* **`)`**
+> *lifetime-dependence-source-name* → **`self`** | *identifier*
 >
-
-The *lifetime-dependent* argument to the lifetime modifier is one of the following:
-
-* *local-parameter-name*: the local name of one of the function parameters, or
-* the token **`self`**, or
-* either of the above preceded by the **`scoped`** keyword, or
-* the token **`immortal`**
-
-This modifier creates a lifetime dependency with the return value used as the dependent value.
-The return value must be nonescapable.
-
-The source value of the resulting dependency can vary.
-In some cases, the source value will be the named parameter or `self` directly.
-However, if the corresponding named parameter or `self` is nonescapable, then that value will itself have an existing lifetime dependency and thus the new dependency might "copy" the source of that existing dependency.
-
-The following table summarizes the possibilities, which depend on the type and mutation modifier of the argument or `self` and the existence of the `scoped` keyword.
-Here, "scoped" indicates that the dependent gains a direct lifetime dependency on the named parameter or `self` and "copied" indicates that the dependent gains a lifetime dependency on the source of an existing dependency:
-
-| mutation modifier  | argument type | without `scoped` | with `scoped` |
-| ------------------ | ------------- | ---------------- | ------------- |
-| borrowed           | escapable     | scoped           | scoped        |
-| inout or mutating  | escapable     | scoped           | scoped        |
-| consuming          | escapable     | Illegal          | Illegal       |
-| borrowed           | nonescapable  | copied           | scoped        |
-| inout or mutating  | nonescapable  | copied           | scoped        |
-| consuming          | nonescapable  | copied           | Illegal       |
-
-Two observations may help in understanding the table above:
-* An escapable argument cannot have a pre-existing lifetime dependency, so copying is never possible in those cases.
-* A consumed argument cannot be the source of a lifetime dependency that will outlive the function call, so only copying is legal in that case.
-
-**Note**: In practice, the `scoped` modifier keyword is likely to be only rarely used.  The rules above were designed to support the known use cases without requiring such a modifier.
-
-#### Initializers
-
-Since nonescapable values cannot be returned without a lifetime dependency,
-initializers for such types must specify a lifetime dependency on one or more arguments.
-We propose allowing initializers to write out an explicit return clause for this case, which permits the use of the same syntax as functions or methods.
-The return type must be exactly the token `Self` or the token sequence `Self?` in the case of a failable initializer:
-
-```swift
-struct S {
-  init(arg1: Type1) -> dependsOn(arg1) Self
-  init?(arg2: Type2) -> dependsOn(arg2) Self?
-}
-```
-
-> Grammar of an initializer declaration:
+> *lifetime-dependence-target-name* → **`self`** | *identifier*
 >
-> *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`throws`***?* *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body* \
-> *initializer-declaration* → *initializer-head* *generic-parameter-clause?* *parameter-clause* **`async`***?* **`rethrows`** *initializer-lifetime-modifier?* *generic-where-clause?* *initializer-body* \
-> *initializer-lifetime-modifier* → `**->**` *lifetime-modifiers* ** **`Self`** \
-> *initializer-lifetime-modifier* → `**->**` *lifetime-modifiers* ** **`Self?`**
-
-The implications of mutation modifiers and argument type on the resulting lifetime dependency exactly follow the rules above for functions and methods.
-
-### Inference Rules
-
-If there is no explicit lifetime dependency on the nonescapable result of a method or function, we will attempt to infer dependencies automatically according these rules in the following order. Subsequent rules are only considered if the prior rules do not generate any inferred dependencies:
-
-1. For methods, functions, and initializers where the return value is nonescapable, we infer a copied lifetime dependency on all parameters of the same nonescapable type. For methods, this rule applies to the implicit `self` parameter like any other parameter: if `self` has the same type as the nonescapable result, then we infer a copied dependency.
-
-2. For methods where the return value is nonescapable, we will infer a dependency against `self`. If `self` is nonescapable, then we infer a copying dependency. If `self` is escapable, and the method is `borrowing` or `mutating`, then we infer a scoped dependency.
-
-3. For functions and initializers that have a nonescapable return value and a single parameter, we infer dependence on that parameter. If the parameter is nonescapable, then we infer a copying dependency; otherwise, we infer a scoped dependency.
-
-For all inference rules, the type of dependence is the same as an explicit `dependsOn(argument)` on the same argument without any `scoped` qualifier based on the argument's type.
-
-**In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
-If a function, method, or initializer has a nonescapable return value, does not have an explicit lifetime dependency annotation, and does not fall into one of the cases above, then that will be a compile-time error.
-
-Consider an example that matches both rule #1 and #2:
-
-```
-struct NE: ~Escapable { ... }
-struct E {
-  func foo(ne: NE) -> /* dependsOn(ne) */ NE
-}
-```
-
-`foo` will not depend on self because rule #1 takes precedence over rule #2.
+> *dependency-kind* → **copy** | **borrow** | **inout**
 
-In this example, both rule #2 and #3 match but are simply redundant:
+This modifier declares a lifetime dependency for the specified target.
+If no *lifetime-dependence-target-name* is specified, then the target is the declaration's return value.
+Otherwise, the target is the parameter named by the *lifetime-dependence-target-name*.
+The target value must be potentially non-`Escapable`.
+A parameter used as a target must additionally either be an `inout` parameter, or `self` in a `mutating` method.
 
-```
-struct NE {
-  init(ne: NE) -> /* dependsOn(ne) */ Self
-}
-```
+The source value of the resulting dependency can vary.
+For a `borrow` or `inout` dependency, the source value will be the named parameter or `self` directly.
+However, if the named parameter or `self` is non-`Escapable`, then that value will itself have an existing lifetime dependency, and a `copy` dependency will copy the source of that existing dependency.
 
 ### Dependency semantics by example
 
-This section illustrates the semantics of lifetime dependence one example at a time for each interesting variation. The following helper functions will be useful: `ContiguousArray.span()` creates a scoped dependence to a nonescapable `Span` result, `copySpan()` creates a copied dependence to a `Span` result, and `parse` uses a `Span`.
+This section illustrates the semantics of lifetime dependence one example at a time for each interesting variation. The following helper functions will be useful: `ContiguousArray.span` creates a non-`Escapable` `Span` result with a scoped dependence to a `ContiguousArray`, `copySpan` creates a new Span with a copied dependence from an existing `Span`, and `parse` uses a `Span`.
 
 ```swift
 extension ContiguousArray {
-  // The returned span depends on the scope of Self.
-  borrowing func span() -> /* dependsOn(scoped self) */ Span<Element> { ... }
+  var span: Span<Element> {
+    @lifetime(borrow self)
+    get {
+      ...
+    }
+  }
 }
 
 // The returned span copies dependencies from 'arg'.
-func copySpan<T>(_ arg: Span<T>) -> /* dependsOn(arg) */ Span<T> { arg }
+@lifetime(copy arg)
+func copySpan<T>(_ arg: Span<T>) -> Span<T> { arg }
 
 func parse(_ span: Span<Int>) { ... }
 ```
@@ -731,24 +708,24 @@ let a: ContiguousArray<Int> = ...
 let span: Span<Int>
 do {
   let a2 = a
-  span = a2.span()
+  span = a2.span
 }
 parse(span) // 🛑 Error: 'span' escapes the scope of 'a2'
 ```
 
-The call to `span()` creates a scoped dependence on `a2`. A scoped dependence is determined by the lifetime of the variable, not the lifetime of the value assigned to that variable. So the lifetime of `span` cannot extend into the larger lifetime of `a`.
+The get of `span` creates a scoped dependence on `a2`. A scoped dependence is determined by the lifetime of the variable, not the lifetime of the value assigned to that variable. So the lifetime of `span` cannot extend into the larger lifetime of `a`.
 
 #### Copied dependence on an immutable variable
 
 Let's contrast scoped dependence shown above with copied dependence on a variable. In this case, the value may outlive the variable it is copied from, as long as it is destroyed before the root of its inherited dependence goes out of scope. A chain of copied dependencies is always rooted in a scoped dependence.
 
-An assignment that copies or moves a nonescapable value from one variable into another **copies** any lifetime dependence from the source value to the destination value. Thus, variable assignment has the same lifetime copy semantics as passing an argument using a `dependsOn()` annotation *without* a `scoped` keyword. So, the statement `let temp = span` has identical semantics to `let temp = copySpan(span)`.
+An assignment that copies or moves a potentially non-`Escapable` value from one variable into another **copies** any lifetime dependence from the source value to the destination value. Thus, assigning `rhs` to a variable has the same lifetime copy semantics as passing an argument using a `@lifetime(copy rhs)` annotation. So, the statement `let temp = span` has identical semantics to `let temp = copySpan(span)`.
 
 ```swift
 let a: ContiguousArray<Int> = arg
 let final: Span<Int>
 do {
-  let span = a.span()
+  let span = a.span
   let temp = span
   final = copySpan(temp)
 }
@@ -764,83 +741,86 @@ First, let's add a mutable method to `Span`:
 
 ```swift
 extension Span {
-  mutating func removePrefix(length: Int) -> /* dependsOn(self) */ Span<T> {
-    let prefix = Span(base: base, count: length)
-    self.base += length
-    self.count -= length
+  @lifetime(copy self)
+  mutating func removePrefix(length: Int) -> Span<T> {
+    let prefix = extracting(0..<length)
+    self = extracting(length..<count)
     return prefix
   }
 }
 ```
 
-A dependence may be copied from a mutable ('inout') variable. In that case, the dependence is inherited from whatever value the mutable variable holds when it is accessed.
+A dependence may be copied from a mutable (`inout`) variable, in this case the .
+When this occurs, the dependence is inherited from whatever value the mutable variable held when the function was invoked.
 
 ```swift
 let a: ContiguousArray<Int> = ...
 var prefix: Span<Int>
 do {
-  var temp = a.span()
-  prefix = temp.droppingPrefix(length: 1) // access 'temp' as 'inout'
+  var temp = a.span
+  prefix = temp.removePrefix(length: 1) // access 'temp' as 'inout'
   // 'prefix' depends on 'a', not 'temp'
 }
 parse(prefix) // âś… Safe: still within lifetime of 'a'
 ```
 
-#### Scoped dependence on 'inout' access
+#### Scoped dependence on `inout` access
 
 Now, let's return to scoped dependence, this time on a mutable variable. This is where exclusivity guarantees come into play. A scoped depenendence extends an access of the mutable variable across all uses of the dependent value. If the variable mutates again before the last use of the dependent, then it is an exclusivity violation.
 
 ```swift
 let a: ContiguousArray<Int> = ...
 a[i] = ...
-let span = a1.span()
+let span = a1.span
 parse(span) // âś… Safe: still within 'span's access on 'a'
 a[i] = ...
 parse(span) // 🛑 Error: simultaneous access of 'a'
 ```
 
-Here, `a1.span()` initiates a 'read' access on `a1`. The first call to `parse(span)` safely extends that read access. The read cannot extend to the second call because a mutation of `a1` occurs before it.
+Here, `a1.span` initiates a 'read' access on `a1`. The first call to `parse(span)` safely extends that read access. The read cannot extend to the second call because a mutation of `a1` occurs before it.
 
 #### Dependence reassignment
 
-We've described how a mutable variable can be the source of a lifetime dependence. Now let's look at nonescapable mutable variables. Being nonescapable means they depend on another lifetime. Being mutable means that dependence may change during reassignment. Reassigning a nonescapable 'inout' sets its lifetime dependence from that point on, up to either the end of the variable's lifetime or its next subsequent reassignment.
+We've described how a mutable variable can be the source of a lifetime dependence. Now, let's look at non-`Escapable` mutable variables. Being non-`Escapable` means they depend on another lifetime. Being mutable means that dependence may change during reassignment. Reassigning a non-`Escapable` `inout` sets its lifetime dependence from that point on, up to either the end of the variable's lifetime or its next subsequent reassignment.
 
 ```swift
 func reassign(_ span: inout Span<Int>) {
   let a: ContiguousArray<Int> = ...
-  span = a.span() // 🛑 Error: 'span' escapes the scope of 'a'
+  span = a.span // 🛑 Error: 'span' escapes the scope of 'a'
 }
 ```
 
 #### Reassignment with argument dependence
 
-If a function takes a nonescapable 'inout' argument, it may only reassign that argument if it is marked dependent on another function argument that provies the source of the dependence.
+If a function takes a non-`Escapable` `inout` parameter, it may only reassign that parameter if it is marked dependent on another function parameter that provides the source of the dependence.
 
 ```swift
-func reassignWithArgDependence(_ span: dependsOn(arg) inout ContiguousArray<Int>, _ arg: ContiguousArray<Int>) {
-  span = arg.span() //  âś… OK: 'span' already depends on 'arg' in the caller's scope.
+@lifetime(span: borrow arg)
+func reassignWithArgDependence(_ span: inout Span<Int>, _ arg: ContiguousArray<Int>) {
+  span = arg.span //  âś… OK: 'span' already depends on 'arg' in the caller's scope.
 }
 ```
 
 #### Conditional reassignment creates conjoined dependence
 
-'inout' argument dependence behaves like a conditional reassignment. After the call, the variable passed to the 'inout' argument has both its original dependence along with a new dependence on the argument that is the source of the argument dependence.
+`inout` argument dependence behaves like a conditional reassignment. After the call, the variable passed to the `inout` argument has both its original dependence along with a new dependence on the argument that is the source of the argument dependence.
 
 ```swift
 let a1: ContiguousArray<Int> = arg
 do {
   let a2: ContiguousArray<Int> = arg
-  var span = a1.span()
+  var span = a1.span
   testReassignArgDependence(&span, a2) // creates a conjoined dependence
   parse(span) // âś… OK: within the lifetime of 'a1' & 'a2'
 }
 parse(span) // 🛑 Error: 'span' escapes the scope of 'a2'
 ```
 
-#### Escapable properties in a nonescapable type
+#### `Escapable` properties in a non-`Escapable` type
 
-An escapable type inevitably contains nonescapable properties. In our `Span` example, the `base` pointer and `count`
-length are both escapable. Accessing an escapable property drops the dependence:
+A non-`Escapable` type inevitably contains `Escapable` properties.
+In our `Span` example, the `base` pointer and `count` length are both `Escapable`.
+There is no dependence after accessing an `Escapable` property:
 
 ```swift
   let pointer: UnsafePointer<T>
@@ -851,10 +831,11 @@ length are both escapable. Accessing an escapable property drops the dependence:
   _ = pointer // âś… OK: pointer has no lifetime dependence
 ```
 
-Internal mutation of a nonescapable type does not create any new dependence and does not require any annotation:
+Internal mutation of `Escapable` properties does not create any new dependence and does not require any annotation:
 
 ```swift
-  mutating /* dependsOn(self: self) */ func skipPrefix(length: Int) {
+
+  mutating func skipPrefix(length: Int) {
     self.base += length  // âś… OK: assigns `base` to a copy of the temporary value
     self.count -= length // âś… OK: assigns `count` to a copy of the temporary value
   }
@@ -876,109 +857,24 @@ Removing a lifetime dependency constraint only affects existing source code in t
 
 ## Alternatives considered
 
-### Different Position
-
-We propose above putting the annotation on the return value, which we believe matches the intuition that the method or property is producing this lifetime dependence alongside the returned value.
-It would also be possible to put an annotation on the parameters instead:
-
-```swift
-func f(@resultDependsOn arg1: ContiguousArray<Int>) -> Span<Int>
-```
-
-Depending on the exact language in use, it could also be more natural to put the annotation after the return value.
-However, we worry that this hides this critical information in cases where the return type is longer or more complex.
-
-```swift
-func f(arg1: ContiguousArray<Int>) -> Span<Int> dependsOn(arg1)
-```
-
 ### Different spellings
 
-An earlier version of this proposal advocated using the existing `borrow`/`mutate`/`consume`/`copy` keywords to specify a particular lifetime dependency semantic:
-```swift
-func f(arg1: borrow ContiguousArray<Int>) -> borrow(arg1) Span<Int>
-```
-This was changed after we realized that there was in practice almost always a single viable semantic for any given situation, so the additional refinement seemed unnecessary.
-
-The currently proposed `dependsOn` spelling was chosen to convey the direction of the dependence, as in:
-
-    func foo(a: A, b: B) -> dependsOn(a) R
-
-This does, however, introduce a keyword with a compound name. Alternatively, we could use a simpler `lifetime` keyword, which better matches the feature description. The general syntax would then be:
-
-> **lifetime**(*target*: [scoped] *source*)
-
-APIs with ambiguous depenencies would then typically be spelled:
-
-    func foo(a: A, b: B) -> lifetime(a) R
-
-### @lifetime annotation
-
-Instead of committing to a final, lightweight syntax, we can start with a single `@lifetime` annotation. It would take this form:
-
-```
-@lifetime(target1.component: [copy|mutate|borrow] source1.component)
-@lifetime(target2.component: [copy|mutate|borrow] source2.component)
-func foo(...)
-```
-
-`target` can be `self`, any parameter name, or, most commonly an empty string which implies the function result. `source` can be `self` or any parameter name. The most common usage would be:
-
-```
-@lifetime(copy arg)
-func foo(label arg: Arg1) -> R {}
-```
-
-The `.component` qualifier is only relevant once we have component lifetimes. See the "Component lifetime" section below.
-
-An annotation has some advantages over a lighter-weight type modifier sytax:
-
-The `@` sigil is helpful to distinguish lifetime dependence information from regular function syntax.
-
-A position-independent annotation has an advantage that the fully expressive syntax is more self-evident. This makes it easier to educate reviewers about what is possible with the syntax.
-
-The type modifier can occur in any type position within a function signature, in including before the `func` keyword for the 'self' type. This has potential readability problems when it comes to more complicated cases. Nested parentheses (`dependsOn(...)`) that can occur anywhere in the signature are visually confusing.
-
-In the future, the single `@lifetime` annotation could be a useful modifier for other kinds declarations such as types and properties:
-
-```
-// Allow two components to have distinct lifetimes...
-struct Pair<T: ~Escapable> {
-  @lifetime
-  var x: T
-
-  @lifetime
-  var y: T
-}
-
-// Allow two components to have dependent lifetimes...
-struct Node: ~Escapable {
-  @lifetime
-  var parent: Node
-
-  @lifetime(parent)
-  var child: Node
-}
-
-// Declare an abstract lifetime and alias it with another lifetime.
-@lifetime(elements: storage.elements)
-struct Container {
-  var storage: Storage
-}
-```
-
-### `where` clause
+Previous revisions of this proposal introduced a `dependsOn` modifier that would be placed syntactically closer to the return type or argument declarations subject to a dependency.
+The authors believe that a more integrated syntax like that is the ultimate right choice for this feature, especially as we develop future directions involving types with multiple lifetime dependencies.
+However, as an attribute, `@lifetime` provides room for experimentation without invasive changes to the language grammar, allowing us to incrementally develop and iterate on the underlying model and implementation.
+Therefore, we think this attribute is the best approach for the current experimental status of lifetime dependencies as a feature.
+Whatever model we ultimately stabilize on ought to support a superset of the functionality proposed here, and it should be possible to mechanically migrate code using `@lifetime` to use the final syntax when it is ready.
 
-Some have advocated for a `where` clause on the function declaration. The function name could stand-in for its result, and directionality could be indicated with a comparison operator:
+### `@lifetime(unchecked)` to disable lifetime dependence checking
 
-`func foo(arg: Arg) -> R where lifetime(foo) < lifetime([copy|borrow|mutate] arg)`
-
-### dependsOn(unchecked) to disable lifetime dependence checking
-
-A `dependsOn(unchecked)` annotation could allow programmers to disable lifetime dependence checking for a function result or argument. For example, the programmer may want to compose a nonescapable result from an immortal value that isn't visible to the compiler:
+A `@lifetime(unchecked)` annotation could allow programmers to disable lifetime dependence checking for a function result or argument. For example, the programmer may want to compose a non-`Escapable` result from an immortal value that isn't visible to the compiler:
 
 ```swift
-init() dependsOn(immortal) {
+// Existing global function that is not lifetime-annotated
+func getGlobalConstant() -> SomeType
+
+@lifetime(immortal)
+init() {
   self.value = getGlobalConstant() // 🛑 ERROR: immortal dependence on a temporary value
 }
 ```
@@ -986,332 +882,275 @@ init() dependsOn(immortal) {
 To avoid the error, the programmer could disable dependence checking on the function result altogether:
 
 ```swift
-init() dependsOn(unchecked) {
+@unsafe @lifetime(unchecked)
+init() {
   self.value = getGlobalConstant() // OK: unchecked dependence.
 }
 ```
 
 This poses a few problems:
 
-1. Declaring a result "unchecked" only affects checking within the function body; it doesn't affect checking in clients of the API, so really shouldn't be part of the API. In the example above, `dependsOn(immortal)` has the correct semantics at the API level.
-
-2. `dependsOn(unchecked)` is a blunt tool for opting out of safety. Experience shows that such tools are overused as workarounds for compiler errors without fixing the problem. A safety workaround should more precisely identify the source of unsafety.
+1. Declaring a result "unchecked" only affects checking within the function body; it doesn't affect checking in clients of the API, so really shouldn't be part of the API. In the example above, `lifetime(immortal)` has the correct semantics at the API level.
 
-3. The more kewords we add to `dependsOn`, the more chance they will collide with a parameter name.
+2. `lifetime(unchecked)` is a blunt tool for opting out of safety. Experience shows that such tools are overused as workarounds for compiler errors without fixing the problem. A safety workaround should more precisely identify the source of unsafety.
 
-`unsafeLifetime` is the propsed tool for disabling dependence checks. Passing `Void` as the dependence source is a reasonable way to convert a nonescaping value to an immortal value:
+`unsafeLifetime` is the proposed tool for disabling dependence checks. Passing `Void` as the dependence source is a reasonable way to convert a nonescaping value to an immortal value:
 
 
 ```swift
+@lifetime(immortal)
 init() dependsOn(immortal) {
   self.value = getGlobalConstant() // OK: unchecked dependence.
-  self = unsafeLifetime(dependent: self, dependsOn: ())
+  unsafe self = unsafeLifetime(dependent: self, dependsOn: ())
 }
 ```
 
 ### Parameter index for lifetime dependencies
 
-Internally, the implementation records dependencies based on the parameter index.
+Internally, the implementation records dependencies canonically based on parameter index.
 This could be exposed as an alternate spelling if there were sufficient demand.
 
 ```swift
-func f(arg1: Type1, arg2: Type2, arg3: Type3) -> dependsOn(0) ReturnType
+@lifetime(borrow 0) // same as `@lifetime(borrow arg1)`
+func f(arg1: Type1, arg2: Type2, arg3: Type3) -> ReturnType
 ```
 
 ## Future Directions
 
-### Lifetime Dependencies for Tuples
-
-It should be possible to return a tuple where one part has a lifetime dependency.
-For example:
-```swift
-func f(a: A, b: B) -> (dependsOn(a) C, B)
-```
-We expect to address this in the near future in a separate proposal.
+### Component lifetimes
 
-### Function type syntax
+One crucial limitation of the lifetime dependency model proposed here is that it models every value as having at most one lifetime dependency, and it applies that one lifetime dependency not only to a non-escapable value but also to any non-escapable values that can be derived from it.
+This fundamental limitation impacts our ability to fully address many of the future directions discussed here.
 
-A function that returns a nonescapable type cannot currently be passed as a nonescaping closure because its dependence information would be lost.
+In the current design, aggregating multiple values merges their scopes:
 
 ```swift
-func f(arg: ArgType) -> dependsOn(arg) NEType
-
-func g1(closure: (ArgType) -> NEType)
+struct Container<Element>: ~Escapable {
+  var a: Element
+  var b: Element
 
-{
-  g1(closure: f) // 🛑 ERROR: function type mismatch 
+  @lifetime(a, b)
+  init(a: Element, b: Element) -> Self {...}
 }
 ```
 
-To address this shortcoming, we plan to extend the `dependsOn(...)` modifier for use in function types. Since function
-types have no parameter names, the parameter position will be identified by an integer literal:
+This has the effect of narrowing the lifetime scope of some components:
 
 ```swift
-func g2(closure: (ArgType) -> dependsOn(0) NE)
-
+var a = ...
 {
-  g2(closure: f) // âś… OK
-}
-```
-
-The parameter index syntax is consistent with how dependencies are already represented internally and in mangled names.
-
-We expect most closures that return nonescapable types to be dependent on the closure context rather than a closure
-parameter--this will be the normal case for passing methods as nonescaping closures. A closure context dependence will
-not affect the spelling of the function type.
-
-### Lifetime dependence for closures
-
-In "Function type syntax", we propose that function types can have explicit `dependsOn` modifiers. When a function type
-returns a nonescapable value but has no explicit `dependsOn` modifier, we plan to infer a dependence on the closure
-context:
-
-```swift
-func g1(closure: () -> NEType) // Inferred: NEType depends on 'closure'
-```
-
-For closure declarations, lifetime dependencies can be inferred on the combined list of captures and closure parameters
-following inference rules similar to those for freestanding functions:
-
-1. For closures where the return value is nonescapable, we infer a copied lifetime dependency on all captures and parameters of the same nonescapable type.
-
-2. For closures that have a nonescapable return value and a single captured value or parameter, we infer dependence on that capture or parameter. If the capture or parameter is nonescapable, then we infer a copying dependency; otherwise, we infer a scoped dependency.
-
-A dependence can be inferred on a closure capture as follows:
-
-```swift
-func f(arg: ArgType) -> dependsOn(arg) NEType
-
-func foo(source: ArgType) {
-  g1 { f(arg: source) } // âś… Inferred: 'closure' result depends on captured 'source'
-}
-```
-
-An explicit dependence on a closure capture can be spelled:
-
-```swift
-func foo(source: ArgType) {
-  g1 { () -> dependsOn(source) NEType in f(arg: source) }
+  let b = ...
+  let c = Container<Element>(a: a, b: b)
+  a = c.a
 }
+use(a) // 🛑 Error: `a` outlives `c`, which is constrained by the lifetime of both `a` and `b`
 ```
 
-Similarly, a dependence can be inferred on a closure parameter:
+In the future, we want to be able to represent the dependencies of multiple stored properties independently. This might look something like this:
 
 ```swift
-func g2(closure: (ArgType) -> dependsOn(0) NEType)
+struct Container<Element>: ~Escapable {
+  var a: Element
+  var b: Element
 
-{
-  g2 { (source: ArgType) in f(arg: source) } // âś… Inferred: 'closure' result depends on 'source' parameter
+  @lifetime(.a: copy arg1, .b: copy arg2)
+  init(arg1: Element, arg2: Element) {
+    ...
+  }
 }
 ```
 
-An explicit dependence on a closure parameter can be spelled:
+This would then allow for the parts of `Component` to be extracted preserving their individual lifetimes:
 
 ```swift
+var a = ...
 {
-  g2 { (source: ArgType) -> dependsOn(source) NEType in f(arg: source) }
+  let b = ...
+  let c = Container<Element>(a: a, b: b)
+  a = c.a
 }
+use(a) // 🛑 OK: `a` copies its lifetime from `c.a`, which in turn copied it from the original `a`
 ```
 
-### Component lifetime
-
-In the current design, aggregating multiple values merges their scopes.
+Extraction operations could also declare that they copy the lifetime of one or more components:
 
 ```swift
-struct Container<Element>: ~Escapable {
-  var a: /*dependsOn(self)*/ Element
-  var b: /*dependsOn(self)*/ Element
-
-  init(a: Element, b: Element) -> dependsOn(a, b) Self {...}
+extension Container {
+  @lifetime(copy self.a)
+  func getA() -> Element {
+    return self.a
+  }
 }
-```
-
-This can have the effect of narrowing the lifetime scope of some components:
 
-```swift
 var a = ...
 {
   let b = ...
   let c = Container<Element>(a: a, b: b)
-  a = c.a // 🛑 Error: `a` outlives `c.a`, which is constrained by the lifetime of `b`
+  a = c.getA()
 }
+use(a) // 🛑 OK: `getA()` copies its lifetime from `c.a`, which in turn copied it from the original `a`
 ```
 
-In the future, the lifetimes of multiple values can be represented independently by attaching a `@lifetime` attribute to a stored property and referring to that property's name inside `dependsOn` annotations:
+The general form of the `@lifetime` syntax in this hypothetical could be thought of as:
 
-```swift
-struct Container<Element>: ~Escapable {
-  @lifetime
-  var a: /*dependsOn(self.a)*/ Element
-  @lifetime
-  var b: /*dependsOn(self.b)*/ Element
+> **`@lifetime`** **`(`** (*target*)? (**`.`** *component*)\* **`:`** *source* (**`.`** *component*) **`)`**
 
-  init(arg1: Element, arg2: Element) -> dependsOn(a: arg1, b: arg2) Self {...}
-}
-```
-
-The nesting level of a component is the inverse of the nesting level of its lifetime. `a` and `b` are nested components of `Container`, but the lifetime of a `Container` instance is nested within both lifetimes of `a` and `b`.
+### Abstract lifetime components
 
-The general form of the `dependsOn` syntax should be thought of as:
+A similar situation comes up when considering collections of non-`Escapable` elements and `Span`.
+Under the current proposal, if `[Contiguous]Array` and `Span` were extended to allow for non-`Escapable` element types, then `Span` would lose the distinction between its own lifetime dependency on the memory of the `Array` and the original dependencies of the elements themselves:
 
-> **dependsOn**(*target*.*component*: *source*.*component*)
+```
+let e1 = NonEscapable(...)
+let e2 = NonEscapable(...)
 
-where the `target` can be inferred from context, but not its component:
+// a is dependent on e1 and e2
+var e: NonEscapable
+do {
+  let a: ContiguousArray = [e1, e2]
 
-Example:
+  // span is dependent on borrowing a
+  let span = a.span
 
-```
-  struct S: ~Escapable {
-    @lifetime
-    let a: T
+  // e copies the dependency from span, borrowing a
+  e = span[randomIndex()]
+}
 
-    dependsOn(self.a: arg1) func foo(arg1: dependsOn(a: arg2) S, arg2: T) -> dependsOn(a: arg2) S
-  }
+use(e) // error: e depends on `a` (even though the original e1 and e2 didn't)
 ```
 
-### Abstract lifetime components
-
-Lifetime dependence is not always neatly tied to stored properties. Say that our `Container` now holds multiple elements within its own storage. We can use a top-level `@lifetime` annotation to name an abstract lifetime for all the elements:
+Lifetime dependence in this case is not neatly tied to stored properties as in the previous example.
+The interesting lifetimes in the case of a `Span` with non-`Escapable` elements are the lifetime of the memory being referenced, as well as the lifetime constraint on the referenced elements.
+We could declare these as abstract lifetime members of `Span`, and allow those member to be referenced in lifetime dependency declarations:
 
 ```swift
-@lifetime(elements)
-struct Container<Element>: ~Escapable {
-  var storage: UnsafeMutablePointer<Element>
-
-  init(element: Element) -> dependsOn(element -> .elements) Self {...}
+@lifetimes(element: Element, memory)
+struct Span<Element: ~Escapable>: ~Escapable {
+  // Accessing an element forwards the lifetime(s) of the elements themselves
+  subscript(i: Int) -> Element {
+    @lifetime(copy self.element)
+    borrow { ... }
+  }
+}
 
-  subscript(position: Int) -> dependsOn(self.elements) Element
+@lifetimes(element: Element)
+extension ContiguousArray<Element: ~Escapable>: ~Escapable {
+  // Accessing a span over the array forwards the lifetime(s) of its elements,
+  // while its memory is dependent on accessing this array.
+  var span: Span<Element> {
+    @lifetime(.memory: borrow self, .element: copy self.element)
+    get { ... }
+  }
 }
 ```
 
-Note that a subscript setter reverses the dependence: `dependsOn(newValue -> .elements)`.
+### Lifetime Dependencies for Tuples
 
-As before, when `Container` held a single element, it can temporarily take ownership of an element without narrowing its lifetime:
+It should be possible to return a tuple in which one or more parts has a lifetime dependency.
+Tuples would benefit greatly from component lifetimes to be able to express the potentially independent lifetimes of the elements.
+For example:
 
 ```swift
-var c1: Container<Element>
-{
-  let c2 = Container<Element>(element: c1[i])
-  c1[i] = c2[i] // OK: c2[i] can outlive c2
-}
+struct A {}
+struct B: ~Escapable {}
+struct C: ~Escapable {}
+
+@lifetime(.0: borrow a, .1: copy b)
+func f(a: A, b: B) -> (C, B)
 ```
 
-Now let's consider a `View` type, similar to `Span`, that provides access to a borrowed container's elements. The lifetime of the view depends on the container's storage. Therefore, the view depends on a *borrow* of the container. The container's elements, however, no longer depend on the container's storage once they have been copied. This can be expressed by giving the view an abstract lifetime for its elements, separate from the view's own lifetime:
+### Function type syntax
+
+This proposal introduces `@lifetime` as a declaration attribute, but does not yet allow the attribute on function types.
+Therefore, a function that returns a non-`Escapable` type cannot currently be passed as a closure because its dependence information would be lost.
 
 ```swift
-@lifetime(elements)
-struct View<Element>: ~Escapable {
-  var storage: UnsafePointer<Element>
+@lifetime(borrow arg)
+func f(arg: ArgType) -> NEType
 
-  init(container: Container)
-    -> dependsOn(container.elements -> .elements) // Copy the lifetime associated with container.elements
-    Self {...}
+func g1(closure: (ArgType) -> NEType)
 
-  subscript(position: Int) -> dependsOn(self.elements) Element
+do {
+  g1(closure: f) // 🛑 ERROR: function type mismatch 
 }
+```
 
-@lifetime(elements)
-struct MutableView<Element>: ~Escapable, ~Copyable {
-  var storage: UnsafeMutablePointer<Element>
-  //...
-}
+To address this shortcoming, the `@lifetime(...)` attribute could be extended to function types as well as declarations.
+Since parameter names are not canonical, function types have no canonical parameter names, so the parameter position would need to be canonically identified by an integer literal:
 
-extension Container {
-  // Require a borrow scope in the caller that borrows the container
-  var view: dependsOn(borrow self) View<Element> { get {...} }
+```swift
+func g2(closure: @lifetime(borrow 0) (ArgType) -> NEType) { ... }
 
-  var mutableView: dependsOn(borrow self) MutableView<Element> { mutating get {...} }
+do {
+  g2(closure: f) // âś… OK
 }
 ```
 
-Now an element can be copied out of a view `v2` and assigned to another view `v1` whose lifetime exceeds the borrow scope that constrains the lifetime of `v2`.
+Internal argument names could potentially be allowed as type sugar:
 
-```swift
-var c1: Container<Element>
-let v1 = c1.mutableView
-{
-  let v2 = c1.view // borrow scope for `v2`
-  v1[i] = v2[i] // OK: v2[i] can outlive v2
-}
 ```
+func g2(closure: @lifetime(borrow arg) (_ arg: ArgType) -> NEType) { ... }
 
-To see this more abstractly, rather than directly assigning, `v1[i] = v2[i]`, we can use a generic interface:
-
-```swift
-func transfer(from: Element, to: dependsOn(from) inout Element) {
-  to = from
-}
+do {
+  // OK, different argument name is not part of the canonical type
+  let f1: @lifetime(borrow a) (_ a: ArgType) -> NEType = f
+  g2(closure: f1)
 
-var c1: Container<Element>
-let v1 = c1.mutableView
-{
-  let v2 = c1.view // borrow scope for `v2`
-  transfer(from: v2[i], to: &v1[i]) // OK: v2[i] can outlive v2
+  // Also OK
+  let f2: @lifetime(borrow 0) (ArgType) -> NEType = f
+  g2(closure: f2)
 }
 ```
 
-### Protocol lifetime requirements
+The parameter index syntax is consistent with how dependencies are represented internally and in mangled names.
 
-Value lifetimes are limited because they provide no way to refer to a lifetime without refering to a concrete type that the lifetime is associated with. To support generic interfaces, protocols need to refer to any lifetime requirements that can appear in interface.
+We expect most closures that return non-`Escapable` types to be dependent on the closure context rather than a closure
+parameter--this will be the normal case for passing methods as nonescaping closures.
+A dependence on context dependence will not affect the spelling of the function type.
 
-Imagine that we want to access view through a protocol. To support returning elements that outlive the view, we need to require an `elements` lifetime requirement:
+### More complex lifetime dependencies for functions
 
-```swift
-@lifetime(elements)
-protocol ViewProtocol {
-  subscript(position: Int) -> dependsOn(self.elements) Element
-}
-```
+Introducing `@lifetime` annotations onto function types is the bare minimum to allow for the use of nonescapable types in function values; however, there are also far more intricate lifetime relationships that function parameters may want to express among their parameters, returns, and those of the outer function.
+The dependencies of their closure context may be nontrivial as well. 
+For example, it would be natural to model a `TaskGroup` as a non-`Escapable` type, to statically enforce the currently dynamically-enforced variant that the task group not be used outside of a `withTaskGroup` block.
+It would furthermore be natural to treat the argument to `addTask` as a nonescaping closure; however, the scope which the closure cannot escape is not the immediate `addTask` call, but the `withTaskGroup` block as a whole.
 
-Let's return to View's initializer;
+In order to express this, function types would likely require a predefined schema of lifetime components in order to express the lifetime constraint of the closure.
 
-```swift
-@lifetime(elements)
-struct View<Element>: ~Escapable {
-  init(container: borrowing Container) ->
-    // Copy the lifetime assoicate with container.elements
-    dependsOn(container.elements -> .elements)
-    Self {...}
-}
 ```
+struct TaskGroup: ~Escapable {
+  @lifetime(body.context: self)
+  func addTask(_ body: () -> ())
 
-This is not a useful initializer, because `View` should not be specific to a concrete `Container` type. Instead, we want `View` to be generic over any container that provides `elements` that can be copied out of the container's storage:
-
-```swift
-@lifetime(elements)
-protocol ElementStorage: ~Escapable {}
-
-@lifetime(elements)
-struct View<Element>: ~Escapable {
-  init(storage: ElementStorage) ->
-    // Copy the lifetime assoicate with storage.elements
-    dependsOn(storage.elements -> .elements)
-    Self {...}
 }
 ```
 
 ### Structural lifetime dependencies
 
-A scoped dependence normally cannot escape the lexical scope of its source variable. It may, however, be convenient to escape the source of that dependence along with any values that dependent on its lifetime. This could be done by moving the ownership of the source into a structure that preserves any dependence relationships. A function that returns a nonescapable type cannot currently depend on the scope of a consuming parameter. But we could lift that restriction provided that the consumed argument is moved into the return value, and that the return type preserves any dependence on that value:
+A scoped dependence normally cannot escape the lexical scope of its source variable. It may, however, be convenient to escape the source of that dependence along with any values that dependent on its lifetime. This could be done by moving the ownership of the source into a structure that preserves any dependence relationships. A function that returns a non-`Escapable` type cannot currently depend on the scope of a consuming parameter. But we could lift that restriction provided that the consumed argument is moved into the return value, and that the return type preserves any dependence on that value:
 
 ```swift
 struct OwnedSpan<T>: ~Copyable {
   let owner: any ~Copyable
-  let span: dependsOn(scope owner) Span<T>
+  @lifetime(borrow owner)
+  let span: Span<T>
 
-  init(owner: consuming any ~Copyable, span: dependsOn(scope owner) Span<T>) -> dependsOn(scoped owner) Self {
+  @lifetime(span: borrow owner)
+  init(owner: consuming any ~Copyable, span: Span<T>) {
     self.owner = owner
     self.span = span
   }
 }
 
 func arrayToOwnedSpan<T>(a: consuming [T]) -> OwnedSpan<T> {
-  OwnedSpan(owner: a, span: a.span())
+  OwnedSpan(owner: a, span: a.span)
 }
 ```
 
 `arrayToOwnedSpan` creates a span with a scoped dependence on an array, then moves both the array and the span into an `OwnedSpan`, which can be returned from the function. This converts the original lexically scoped dependence into a structural dependence.
 
-## Acknowledgements
+## Acknowledgments
 
 Dima Galimzianov provided several examples for Future Directions.
+
+Thanks to Gabor Horvath, Michael Ilseman, Guillaume Lessard, and Karoy Lorentey for adopting this functionality in C++ interop and new standard library APIs and providing valuable feedback.

From e43a19ed4132bdd52f769fa606fd519fc3aa939c Mon Sep 17 00:00:00 2001
From: Joe Groff <jgroff@apple.com>
Date: Mon, 24 Mar 2025 11:52:33 -0700
Subject: [PATCH 53/59] Fix typos

---
 proposals/NNNN-lifetime-dependency.md | 49 +++++++++++++++------------
 1 file changed, 27 insertions(+), 22 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 7d9636b468..e120349858 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -473,7 +473,8 @@ init() {
 `<global constant>` must be valid over the entire program.
 
 `@lifetime(immortal)` is not a way to suppress dependence in cases where the source value has unknown
-lifetime. Composing the result from a transient value, such as an UnsafePointer, is incorrect:
+lifetime.
+Composing the result from a transient value, such as an UnsafePointer, is incorrect:
 
 ```swift
 @lifetime(immortal)
@@ -493,7 +494,8 @@ init() {
 
 ### Depending on an escapable `BitwiseCopyable` value
 
-The source of a lifetime dependence may be an escapable `BitwiseCopyable` value. This is useful in the implementation of data types that internally use `UnsafePointer`:
+The source of a lifetime dependence may be an escapable `BitwiseCopyable` value.
+This is useful in the implementation of data types that internally use `UnsafePointer`:
 
 ```swift
 struct Span<T>: ~Escapable {
@@ -506,7 +508,11 @@ struct Span<T>: ~Escapable {
 }
 ```
 
-When the source of a dependence is escapable and `BitwiseCopyable`, then the operation must be marked as `@unsafe` when using strict memory safety as introduced in [SE-0458](0458-strict-memory-safety.md). By convention, the argument label should also include the word `unsafe` in its name, as in `unsafeBaseAddress` above. This communicates to anyone who calls the function that they are reponsible for ensuring that the value that the result depends on is valid over all uses of the result. The compiler can't guarantee safety because `BitwiseCopyable` types do not have a formal point at which the value is destroyed. Specifically, for `UnsafePointer`, the compiler does not know which object owns the pointed-to storage.
+When the source of a dependence is escapable and `BitwiseCopyable`, then the operation must be marked as `@unsafe` when using strict memory safety as introduced in [SE-0458](0458-strict-memory-safety.md).
+By convention, the argument label should also include the word `unsafe` in its name, as in `unsafeBaseAddress` above.
+This communicates to anyone who calls the function that they are reponsible for ensuring that the value that the result depends on is valid over all uses of the result.
+The compiler can't guarantee safety because `BitwiseCopyable` types do not have a formal point at which the value is destroyed.
+Specifically, for `UnsafePointer`, the compiler does not know which object owns the pointed-to storage.
 
 ```swift
 var span: Span<T>?
@@ -514,7 +520,7 @@ let buffer: UnsafeBufferPointer<T>
 do {
   let storage = Storage(...)
   buffer = storage.buffer
-  span = Span(unsafeBaseAddress: buffer.baseAddress!, count: buffer.count)
+  span = unsafe Span(unsafeBaseAddress: buffer.baseAddress!, count: buffer.count)
   // 🔥 'storage' may be destroyed
 }
 decode(span!) // 👿 Undefined behavior: dangling pointer
@@ -524,6 +530,7 @@ Normally, `UnsafePointer` lifetime guarantees naturally fall out of closure-taki
 
 ```swift
 extension Storage {
+  @unsafe
   public func withUnsafeBufferPointer<R>(
     _ body: (UnsafeBufferPointer<Element>) throws -> R
   ) rethrows -> R {
@@ -532,8 +539,8 @@ extension Storage {
 }
 
 let storage = Storage(...)
-storage.withUnsafeBufferPointer { buffer in
-  let span = Span(unsafeBaseAddress: buffer.baseAddress!, count: buffer.count)
+unsafe storage.withUnsafeBufferPointer { buffer in
+  let span = unsafe Span(unsafeBaseAddress: buffer.baseAddress!, count: buffer.count)
   decode(span) // âś… Safe: 'buffer' is always valid within the closure.
 }
 ```
@@ -571,7 +578,7 @@ extension Span {
   consuming func dropFirst() -> Span<Element> {
     let local = Span(base: self.base + 1, count: self.count - 1)
     // 'local' can persist after 'self' is destroyed.
-    return unsafeLifetime(dependent: local, dependsOn: self)
+    return unsafe unsafeLifetime(dependent: local, dependsOn: self)
   }
 }
 ```
@@ -584,7 +591,7 @@ Since `self.base` is an `Escapable` value, it does not propagate the lifetime de
 @lifetime(immortal)
 init() {
   self.value = getGlobalConstant() // OK: unchecked dependence.
-  self = unsafeLifetime(dependent: self, dependsOn: ())
+  self = unsafe unsafeLifetime(dependent: self, dependsOn: ())
 }
 ```
 
@@ -593,7 +600,7 @@ init() {
 ### Relation to `Escapable`
 
 The lifetime dependencies described in this document can be applied only to potentially non-`Escapable` return values.
-Further, any return value that is non-`Escapable` must declare a lifetime dependency.
+Further, any return value that is potentially non-`Escapable` must declare a lifetime dependency.
 In particular, this implies that the initializer for a non-`Escapable` type must have at least one argument or else specify `@lifetime(immortal)`.
 
 ```swift
@@ -602,10 +609,9 @@ struct S: ~Escapable {
 }
 ```
 
-In generic contexts, `~Escapable` indicates that a type is *not required* to be `Escapable`, but is *not* a strict indication that a type is not `Escapable` at all.
-Generic types can be conditionally `Escapable`, and type parameters to generic functions that are declared `~Escapable` can be given `Escapable` types as arguments.
+In generic contexts, `~Escapable` indicates that a type is *not required* to be `Escapable`, but the type may be conditionally `Escapable` depending on generic substitutions.
 This proposal refers to types in these situations as "potentially non-`Escapable`" types.
-Return types that are potentially non-`Escapable` require lifetime dependencies to be specified, but when they are used in contexts where a value becomes `Escapable` due to the type parameters used, then those lifetime dependencies lose their effect, since
+Declarations with return types that are potentially non-`Escapable` require lifetime dependencies to be specified, but when those declarations are used in contexts where their result becomes `Escapable` due to the type arguments used, then those lifetime dependencies have no effect:
 
 ```swift
 // `Optional` is `Escapable` only when its `Wrapped` type is `Escapable`, and
@@ -618,25 +624,24 @@ func optionalize<T: ~Escapable>(_ value: T) -> T? {
     return value
 }
 
-// When used with non-Escapable types, `optionalize`'s dependencies are imposed
+// When used with non-Escapable types, `optionalize`'s dependencies are imposed.
 var maybeSpan: Span<Int>? = nil
 do {
   let a: ContiguousArray<Int> = ...
   
   maybeSpan = optionalize(a.span)
-  // maybeSpan is now dependent on borrowing `a`, copying the dependency from
-  // `a.span` through `optionalize`
+  // `maybeSpan` is now dependent on borrowing `a`, copying the dependency from
+  // `a.span` through `optionalize`.
 }
 print(maybeSpan?[0]) // error, `maybeSpan` used outside of lifetime constraint
 
-// But when used with Escapable types, the dependencies lose their effect
+// But when used with Escapable types, the dependencies lose their effect.
 var maybeString: String? = 0
 do {
     let s = "strings are eternal"
     maybeString = optionalize(s)
 }
-print(maybeString) // OK, String? is `Escapable`, no lifetime constraint
-
+print(maybeString) // OK, String? is `Escapable`, so has no lifetime constraint.
 ```
 
 ### Basic Semantics
@@ -656,7 +661,7 @@ The compiler must issue a diagnostic if any of the above cannot be satisfied.
 
 ### Grammar
 
-This new syntax adds a `@lifetime` attribute that can be applied to function, initializer, and property accessor declarations:
+This proposal adds a `@lifetime` attribute that can be applied to function, initializer, and property accessor declarations:
 
 > *lifetime-attribute* → **`@`** **`lifetime`** **`(`** *lifetime-dependence-list* **`)`**
 >
@@ -674,7 +679,7 @@ This modifier declares a lifetime dependency for the specified target.
 If no *lifetime-dependence-target-name* is specified, then the target is the declaration's return value.
 Otherwise, the target is the parameter named by the *lifetime-dependence-target-name*.
 The target value must be potentially non-`Escapable`.
-A parameter used as a target must additionally either be an `inout` parameter, or `self` in a `mutating` method.
+Additionally, a parameter used as a target must either be an `inout` parameter or `self` in a `mutating` method.
 
 The source value of the resulting dependency can vary.
 For a `borrow` or `inout` dependency, the source value will be the named parameter or `self` directly.
@@ -750,7 +755,7 @@ extension Span {
 }
 ```
 
-A dependence may be copied from a mutable (`inout`) variable, in this case the .
+A dependence may be copied from a mutable (`inout`) variable.
 When this occurs, the dependence is inherited from whatever value the mutable variable held when the function was invoked.
 
 ```swift
@@ -929,7 +934,7 @@ struct Container<Element>: ~Escapable {
   var a: Element
   var b: Element
 
-  @lifetime(a, b)
+  @lifetime(copy a, copy b)
   init(a: Element, b: Element) -> Self {...}
 }
 ```

From 5bc62021ade654493f2023b78e306b9238f18cd4 Mon Sep 17 00:00:00 2001
From: Joe Groff <jgroff@apple.com>
Date: Tue, 25 Mar 2025 17:12:04 -0700
Subject: [PATCH 54/59] More revisions from feedback

- `unsafeLifetime` is currently implemented as `_overrideLifetime`
- Clarify distinction between using an inout parameter as a source or target,
  and point out what occurs (nothing) if a parameter is both the source and
  target of a dependency
- Give an explicit example of conjoined dependence with multiple lifetimes
  on the same target
---
 proposals/NNNN-lifetime-dependency.md | 81 +++++++++++++++++++++------
 1 file changed, 63 insertions(+), 18 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index e120349858..6776f6c1ac 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -15,9 +15,9 @@ This is deeply related to `~Escapable` types, as introduced in [SE-0446](0446-no
 **Edited** (March 20, 2025):
 
 - Replaced `dependsOn` return type modifier with a declaration-level `@lifetime` attribute.
-Removed dependency inference rules.
+    Removed dependency inference rules.
 - Integrated links to proposals SE-0446 (`Escapable`), SE-0447 (`Span`), SE-0456 (`Span`-producing properties), and SE-0467 (`MutableSpan`) that have undergone review.
-- Added SE-0458 `@unsafe` annotations to the `unsafeLifetime` standard library functions, and added `@unsafe` as a requirement for APIs using `BitwiseCopyable` lifetime dependencies under strict memory safety.
+- Added SE-0458 `@unsafe` annotations to the `_overrideLifetime` standard library functions, and added `@unsafe` as a requirement for APIs using `BitwiseCopyable` lifetime dependencies under strict memory safety.
 
 **Edited** (April 12, 2024): Changed `@dependsOn` to `dependsOn` to match the current implementation.
 
@@ -547,17 +547,17 @@ unsafe storage.withUnsafeBufferPointer { buffer in
 
 ### Standard library extensions
 
-#### `unsafeLifetime` helper functions
+#### `_overrideLifetime` helper functions
 
-The following two helper functions will be added for implementing low-level data types:
+The following helper functions will be added for implementing low-level data types:
 
 ```swift
 /// Replace the current lifetime dependency of `dependent` with a new copied lifetime dependency on `source`.
 ///
 /// Precondition: `dependent` has an independent copy of the dependent state captured by `source`.
 @unsafe @lifetime(copy source)
-func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
-  dependent: consuming T, dependsOn source: borrowing U)
+func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
+  dependent: consuming T, copying source: borrowing U)
   -> T { ... }
 
 /// Replace the current lifetime dependency of `dependent` with a new scoped lifetime dependency on `source`.
@@ -565,9 +565,19 @@ func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
 /// Precondition: `dependent` depends on state that remains valid until either:
 /// (a) `source` is either destroyed if it is immutable,
 /// or (b) exclusive to `source` access ends if it is a mutable variable.
-@unsafe @lifetime(borrowing source)
-func unsafeLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
-  dependent: consuming T, scoped source: borrowing U)
+@unsafe @lifetime(borrow source)
+func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
+  dependent: consuming T, borrowing source: borrowing U)
+  -> T {...}
+
+/// Replace the current lifetime dependency of `dependent` with a new scoped lifetime dependency on `source`.
+///
+/// Precondition: `dependent` depends on state that remains valid until either:
+/// (a) `source` is either destroyed if it is immutable,
+/// or (b) exclusive to `source` access ends if it is a mutable variable.
+@unsafe @lifetime(inout source)
+func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
+  dependent: consuming T, mutating source: inout U)
   -> T {...}
 ```
 
@@ -578,20 +588,20 @@ extension Span {
   consuming func dropFirst() -> Span<Element> {
     let local = Span(base: self.base + 1, count: self.count - 1)
     // 'local' can persist after 'self' is destroyed.
-    return unsafe unsafeLifetime(dependent: local, dependsOn: self)
+    return unsafe _overrideLifetime(dependent: local, dependsOn: self)
   }
 }
 ```
 
-Since `self.base` is an `Escapable` value, it does not propagate the lifetime dependence of its container. Without the call to `unsafeLifetime`, `local` would be limited to the local scope of the value retrieved from `self.base`, and could not be returned from the method. In this example, `unsafeLifetime` communicates that all of the dependent state from `self` has been *copied* into `local`, and, therefore, `local` can persist after `self` is destroyed.
+Since `self.base` is an `Escapable` value, it does not propagate the lifetime dependence of its container. Without the call to `_overrideLifetime`, `local` would be limited to the local scope of the value retrieved from `self.base`, and could not be returned from the method. In this example, `_overrideLifetime` communicates that all of the dependent state from `self` has been *copied* into `local`, and, therefore, `local` can persist after `self` is destroyed.
 
-`unsafeLifetime` can also be used to construct an immortal value where the compiler cannot prove immortality by passing a `Void` value as the source of the dependence:
+`_overrideLifetime` can also be used to construct an immortal value where the compiler cannot prove immortality by passing a `Void` value as the source of the dependence:
 
 ```swift
 @lifetime(immortal)
 init() {
   self.value = getGlobalConstant() // OK: unchecked dependence.
-  self = unsafe unsafeLifetime(dependent: self, dependsOn: ())
+  self = unsafe _overrideLifetime(dependent: self, dependsOn: ())
 }
 ```
 
@@ -651,11 +661,11 @@ This relationship obeys the following requirements:
 
 * The dependent value must be potentially non-`Escapable`.
 
-* The dependent value's lifetime must not be longer than that of the source value.
+* The dependent value's lifetime must be as long as or shorter than that of the source value.
 
 * The dependent value is treated as an ongoing access to the source value.
-  Following Swift's usual exclusivity rules, the source value may not be mutated during the lifetime of the dependent value;
-  if the access is a mutating access, the source value is further prohibited from being accessed at all during the lifetime of the dependent value.
+    Following Swift's usual exclusivity rules, the source value may not be mutated during the lifetime of the dependent value;
+    if the access is a mutating access, the source value is further prohibited from being accessed at all during the lifetime of the dependent value.
 
 The compiler must issue a diagnostic if any of the above cannot be satisfied.
 
@@ -806,6 +816,23 @@ func reassignWithArgDependence(_ span: inout Span<Int>, _ arg: ContiguousArray<I
 }
 ```
 
+This means that an `inout` parameter of potentially non-`Escapable` type can interact with lifetimes in three ways:
+
+- as the source of a scoped dependency, as in `@lifetime([<target>:] inout x)`
+- as the source of a copied dependency, as in `@lifetime([<target>:] copy x)`
+- as the target of a dependency, as in `@lifetime(x: <dependency>)`
+
+so it is worth restating the behavior here to emphasize the distinctions.
+A scoped dependency `@lifetime(inout x)` indicates that the target's lifetime is constrained by exclusive access to `x`.
+A copied dependency `@lifetime(copy x)` indicates that the target copies its lifetime constraint from value of `x` when the callee *begins* execution.
+As the target of a dependency, `@lifetime(x: <dependency>)` indicates the lifetime constraint added to the value of `x` after the callee *ends* execution.
+
+By composition, an `inout` parameter could appear as both the source and target of a dependency, though it is not useful:
+
+- `@lifetime(x: inout x)` states that the value of `x` on return from the callee is dependent on exclusive access to the variable `x`.
+    This would have the net effect of making the argument to `x` inaccessible for the rest of its lifetime, since it is exclusively accessed by the value inside of itself.
+- `@lifetime(x: copy x)` states that the value of `x` on return from the callee copies its dependency from the value of `x` when the function began execution, in effect stating that the lifetime dependency does not change.
+
 #### Conditional reassignment creates conjoined dependence
 
 `inout` argument dependence behaves like a conditional reassignment. After the call, the variable passed to the `inout` argument has both its original dependence along with a new dependence on the argument that is the source of the argument dependence.
@@ -821,6 +848,24 @@ do {
 parse(span) // 🛑 Error: 'span' escapes the scope of 'a2'
 ```
 
+#### Explicit conjoined dependence
+
+A declaration can also express a conjoined dependence explicitly by applying multiple lifetime dependencies to the same target:
+
+```swift
+struct Pair<T: ~Escapable, U: ~Escapable>: ~Escapable {
+    var first: T
+    var second: U
+
+    // A Pair cannot outlive the lifetime of either of its fields.
+    @lifetime(copy first, copy second)
+    init(first: T, second: U) {
+        self.first = first
+        self.second = second
+    }
+}
+```
+
 #### `Escapable` properties in a non-`Escapable` type
 
 A non-`Escapable` type inevitably contains `Escapable` properties.
@@ -899,14 +944,14 @@ This poses a few problems:
 
 2. `lifetime(unchecked)` is a blunt tool for opting out of safety. Experience shows that such tools are overused as workarounds for compiler errors without fixing the problem. A safety workaround should more precisely identify the source of unsafety.
 
-`unsafeLifetime` is the proposed tool for disabling dependence checks. Passing `Void` as the dependence source is a reasonable way to convert a nonescaping value to an immortal value:
+`_overrideLifetime` is the proposed tool for disabling dependence checks. Passing `Void` as the dependence source is a reasonable way to convert a nonescaping value to an immortal value:
 
 
 ```swift
 @lifetime(immortal)
 init() dependsOn(immortal) {
   self.value = getGlobalConstant() // OK: unchecked dependence.
-  unsafe self = unsafeLifetime(dependent: self, dependsOn: ())
+  unsafe self = _overrideLifetime(dependent: self, dependsOn: ())
 }
 ```
 

From 8083f24fb632f20237c23314290500cb1ef1a9ff Mon Sep 17 00:00:00 2001
From: Joe Groff <arcata@gmail.com>
Date: Wed, 26 Mar 2025 10:09:34 -0700
Subject: [PATCH 55/59] Apply suggestions from code review

Thanks @glessard for catching these typos!

Co-authored-by: Guillaume Lessard <glessard@tffenterprises.com>
---
 proposals/NNNN-lifetime-dependency.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 6776f6c1ac..fbf3d1af17 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -218,7 +218,7 @@ let ref2 = ref1.extracting(4 ..< ref1.count) // ref2 also cannot outlive a
 ```
 
 After `ref1.extracting(4 ..< ref1.count)`, the lifetime of `ref2` does not depend on `ref1`.
-The `extracting` method **copies** `ref1`s lifetime depenence onto `ref2`.
+The `extracting` method **copies** `ref1`s lifetime dependence onto `ref2`.
 `ref2` effectively **inherits** the same lifetime dependency on `a` as `ref1`.
 We may also refer to a lifetime dependence that has been copied from another value as an "inherited" dependence.
 Since both `ref1` and `ref2` have borrowing scoped dependencies on `a`, they can be used simultaneously:
@@ -781,7 +781,7 @@ parse(prefix) // âś… Safe: still within lifetime of 'a'
 
 #### Scoped dependence on `inout` access
 
-Now, let's return to scoped dependence, this time on a mutable variable. This is where exclusivity guarantees come into play. A scoped depenendence extends an access of the mutable variable across all uses of the dependent value. If the variable mutates again before the last use of the dependent, then it is an exclusivity violation.
+Now, let's return to scoped dependence, this time on a mutable variable. This is where exclusivity guarantees come into play. A scoped dependence extends an access of the mutable variable across all uses of the dependent value. If the variable mutates again before the last use of the dependent, then it is an exclusivity violation.
 
 ```swift
 let a: ContiguousArray<Int> = ...

From 7b753f5f5c3b91471dabf551bcf0842b9ab25e3c Mon Sep 17 00:00:00 2001
From: Joe Groff <jgroff@apple.com>
Date: Wed, 26 Mar 2025 10:11:56 -0700
Subject: [PATCH 56/59] More clarifications

- Parameters are referred to by their internal binding name as target or source
  of a dependency
- No effect on function types yet
- Unsafe dependencies are specifically on `Escapable & BitwiseCopyable` types
- Removed misleading example
---
 proposals/NNNN-lifetime-dependency.md | 30 ++++++++++++++-------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index fbf3d1af17..9b24dc81d0 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -17,7 +17,7 @@ This is deeply related to `~Escapable` types, as introduced in [SE-0446](0446-no
 - Replaced `dependsOn` return type modifier with a declaration-level `@lifetime` attribute.
     Removed dependency inference rules.
 - Integrated links to proposals SE-0446 (`Escapable`), SE-0447 (`Span`), SE-0456 (`Span`-producing properties), and SE-0467 (`MutableSpan`) that have undergone review.
-- Added SE-0458 `@unsafe` annotations to the `_overrideLifetime` standard library functions, and added `@unsafe` as a requirement for APIs using `BitwiseCopyable` lifetime dependencies under strict memory safety.
+- Added SE-0458 `@unsafe` annotations to the `_overrideLifetime` standard library functions, and added `@unsafe` as a requirement for APIs using `Escapable & BitwiseCopyable` lifetime dependencies under strict memory safety.
 
 **Edited** (April 12, 2024): Changed `@dependsOn` to `dependsOn` to match the current implementation.
 
@@ -483,18 +483,9 @@ init(pointer: UnsafePointer<T>) {
 }
 ```
 
-We could run into the same problem with any transient value, like a file descriptor, or even a class object:
+### Depending on an `Escapable & BitwiseCopyable` value
 
-```swift
-@lifetime(immortal)
-init() {
-  self.value = Object() // 🛑 Incorrect
-}
-```
-
-### Depending on an escapable `BitwiseCopyable` value
-
-The source of a lifetime dependence may be an escapable `BitwiseCopyable` value.
+The source of a lifetime dependence may be an `Escapable & BitwiseCopyable` value.
 This is useful in the implementation of data types that internally use `UnsafePointer`:
 
 ```swift
@@ -688,12 +679,14 @@ This proposal adds a `@lifetime` attribute that can be applied to function, init
 This modifier declares a lifetime dependency for the specified target.
 If no *lifetime-dependence-target-name* is specified, then the target is the declaration's return value.
 Otherwise, the target is the parameter named by the *lifetime-dependence-target-name*.
+A parameter is referenced by its "internal" binding name rather than by its label name.
 The target value must be potentially non-`Escapable`.
 Additionally, a parameter used as a target must either be an `inout` parameter or `self` in a `mutating` method.
 
 The source value of the resulting dependency can vary.
 For a `borrow` or `inout` dependency, the source value will be the named parameter or `self` directly.
 However, if the named parameter or `self` is non-`Escapable`, then that value will itself have an existing lifetime dependency, and a `copy` dependency will copy the source of that existing dependency.
+As with the target, a parameter is referenced by its "internal" binding name rather than by its label name.
 
 ### Dependency semantics by example
 
@@ -827,12 +820,14 @@ A scoped dependency `@lifetime(inout x)` indicates that the target's lifetime is
 A copied dependency `@lifetime(copy x)` indicates that the target copies its lifetime constraint from value of `x` when the callee *begins* execution.
 As the target of a dependency, `@lifetime(x: <dependency>)` indicates the lifetime constraint added to the value of `x` after the callee *ends* execution.
 
-By composition, an `inout` parameter could appear as both the source and target of a dependency, though it is not useful:
+By composition, an `inout` parameter could appear as both the source and target of a dependency, though the behavior is not useful in either case:
 
 - `@lifetime(x: inout x)` states that the value of `x` on return from the callee is dependent on exclusive access to the variable `x`.
     This would have the net effect of making the argument to `x` inaccessible for the rest of its lifetime, since it is exclusively accessed by the value inside of itself.
 - `@lifetime(x: copy x)` states that the value of `x` on return from the callee copies its dependency from the value of `x` when the function began execution, in effect stating that the lifetime dependency does not change.
 
+Therefore, we propose to disallow this.
+
 #### Conditional reassignment creates conjoined dependence
 
 `inout` argument dependence behaves like a conditional reassignment. After the call, the variable passed to the `inout` argument has both its original dependence along with a new dependence on the argument that is the source of the argument dependence.
@@ -1071,7 +1066,7 @@ use(e) // error: e depends on `a` (even though the original e1 and e2 didn't)
 
 Lifetime dependence in this case is not neatly tied to stored properties as in the previous example.
 The interesting lifetimes in the case of a `Span` with non-`Escapable` elements are the lifetime of the memory being referenced, as well as the lifetime constraint on the referenced elements.
-We could declare these as abstract lifetime members of `Span`, and allow those member to be referenced in lifetime dependency declarations:
+We could declare these as abstract lifetime members of `Span`, and allow those members to be referenced in lifetime dependency declarations:
 
 ```swift
 @lifetimes(element: Element, memory)
@@ -1109,6 +1104,13 @@ struct C: ~Escapable {}
 func f(a: A, b: B) -> (C, B)
 ```
 
+### First-class nonescaping functions
+
+This proposal does not by itself affect how function types work in Swift,
+whether escapable or not.
+However, nonescaping functions are currently less than first-class, since they can only appear as parameters to other functions, cannot be used as generic type arguments, and their values can only be used in limited circumstances.
+Since the `Escapable` protocol and lifetime dependencies introduce lifetime-constrained values as a general concept in the language, it would make sense to integrate that capability to function types, allowing for nonescaping functions to be modeled as functions whose capture context has one or more lifetime dependencies.
+
 ### Function type syntax
 
 This proposal introduces `@lifetime` as a declaration attribute, but does not yet allow the attribute on function types.

From 9b600fe6c847e7e0a84009acc079a99ff5786ffb Mon Sep 17 00:00:00 2001
From: Joe Groff <jgroff@apple.com>
Date: Wed, 26 Mar 2025 12:00:07 -0700
Subject: [PATCH 57/59] use official names for parameter name and argument
 label

---
 proposals/NNNN-lifetime-dependency.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index 9b24dc81d0..cfa0eea2e7 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -679,14 +679,14 @@ This proposal adds a `@lifetime` attribute that can be applied to function, init
 This modifier declares a lifetime dependency for the specified target.
 If no *lifetime-dependence-target-name* is specified, then the target is the declaration's return value.
 Otherwise, the target is the parameter named by the *lifetime-dependence-target-name*.
-A parameter is referenced by its "internal" binding name rather than by its label name.
+A parameter is referenced by its parameter name (the "internal" name used to refer to the value in the function body) rather than by its argument label.
 The target value must be potentially non-`Escapable`.
 Additionally, a parameter used as a target must either be an `inout` parameter or `self` in a `mutating` method.
 
 The source value of the resulting dependency can vary.
 For a `borrow` or `inout` dependency, the source value will be the named parameter or `self` directly.
 However, if the named parameter or `self` is non-`Escapable`, then that value will itself have an existing lifetime dependency, and a `copy` dependency will copy the source of that existing dependency.
-As with the target, a parameter is referenced by its "internal" binding name rather than by its label name.
+As with the target, a source parameter is referenced by its "internal" parameter name rather than by its argument label.
 
 ### Dependency semantics by example
 

From ef1c5e95ea29a45e86d1016b903836cdc71ea705 Mon Sep 17 00:00:00 2001
From: Joe Groff <jgroff@apple.com>
Date: Tue, 1 Apr 2025 10:21:18 -0700
Subject: [PATCH 58/59] Adjust `_overrideLifetime` docs to match current stdlib
 implementation

---
 proposals/NNNN-lifetime-dependency.md | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index cfa0eea2e7..fca42369ed 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -548,7 +548,7 @@ The following helper functions will be added for implementing low-level data typ
 /// Precondition: `dependent` has an independent copy of the dependent state captured by `source`.
 @unsafe @lifetime(copy source)
 func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
-  dependent: consuming T, copying source: borrowing U)
+  _ dependent: consuming T, copying source: borrowing U)
   -> T { ... }
 
 /// Replace the current lifetime dependency of `dependent` with a new scoped lifetime dependency on `source`.
@@ -558,7 +558,7 @@ func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
 /// or (b) exclusive to `source` access ends if it is a mutable variable.
 @unsafe @lifetime(borrow source)
 func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
-  dependent: consuming T, borrowing source: borrowing U)
+  _ dependent: consuming T, borrowing source: borrowing U)
   -> T {...}
 
 /// Replace the current lifetime dependency of `dependent` with a new scoped lifetime dependency on `source`.
@@ -568,7 +568,7 @@ func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
 /// or (b) exclusive to `source` access ends if it is a mutable variable.
 @unsafe @lifetime(inout source)
 func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
-  dependent: consuming T, mutating source: inout U)
+  _ dependent: consuming T, mutating source: inout U)
   -> T {...}
 ```
 
@@ -579,7 +579,7 @@ extension Span {
   consuming func dropFirst() -> Span<Element> {
     let local = Span(base: self.base + 1, count: self.count - 1)
     // 'local' can persist after 'self' is destroyed.
-    return unsafe _overrideLifetime(dependent: local, dependsOn: self)
+    return unsafe _overrideLifetime(local, copying: self)
   }
 }
 ```
@@ -592,7 +592,7 @@ Since `self.base` is an `Escapable` value, it does not propagate the lifetime de
 @lifetime(immortal)
 init() {
   self.value = getGlobalConstant() // OK: unchecked dependence.
-  self = unsafe _overrideLifetime(dependent: self, dependsOn: ())
+  self = unsafe _overrideLifetime(self, copying: ())
 }
 ```
 
@@ -946,7 +946,7 @@ This poses a few problems:
 @lifetime(immortal)
 init() dependsOn(immortal) {
   self.value = getGlobalConstant() // OK: unchecked dependence.
-  unsafe self = _overrideLifetime(dependent: self, dependsOn: ())
+  unsafe self = _overrideLifetime(self, copying: ())
 }
 ```
 

From ac38ca53db0f8205ae75d0cbd04690af6a65c230 Mon Sep 17 00:00:00 2001
From: Meghana Gupta <meghana_gupta@apple.com>
Date: Thu, 3 Apr 2025 15:32:59 -0700
Subject: [PATCH 59/59] Replace @lifetime(inout arg) -> @lifetime(&arg)

---
 proposals/NNNN-lifetime-dependency.md | 34 +++++++++++++--------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/proposals/NNNN-lifetime-dependency.md b/proposals/NNNN-lifetime-dependency.md
index fca42369ed..170ac181eb 100644
--- a/proposals/NNNN-lifetime-dependency.md
+++ b/proposals/NNNN-lifetime-dependency.md
@@ -166,16 +166,16 @@ Let's now consider the `MutableSpan<T>` type from [SE-0467](0467-MutableSpan.md)
 Here's one way such a value might be produced from an owning array:
 
 ```swift
-@lifetime(inout to)
+@lifetime(&to)
 func mutatingSpan<Element>(to: inout ContiguousArray<Element>, count: Int) -> MutatingSpan<Element> {
   ... construct a MutatingSpan ...
 }
 ```
 
 We’ve written this example as a free function rather than as a method to show how this annotation syntax can be used to express constraints that apply to a particular parameter other than `self`.
-The `@lifetime(inout to)` annotation indicates that the returned value depends on the argument named `to`.
+The `@lifetime(&to)` annotation indicates that the returned value depends on the argument named `to`.
 Because `count` is not mentioned in the lifetime dependency, that argument does not participate.
-Instead of `borrow`, this annotation uses the `inout` keyword to indicate that the returned span depends on **mutating** exclusive access to the `to` parameter rather than borrowed access.
+Instead of `borrow`, this annotation uses the `&` sigil to indicate that the returned span depends on **mutating** exclusive access to the `to` parameter rather than borrowed access.
 
 Similar to the previous example:
 
@@ -185,7 +185,7 @@ However, by contrast with the previous `borrow` dependency:
 
 * No other read or write access to the array will be allowed for as long as the returned value exists, since the dependency requires exclusivity.
 
-In both the `inout` and the `borrow` dependency case, the lifetime of the return value is "scoped" to an access into the lifetime of the original value.
+In both the `&` and the `borrow` dependency case, the lifetime of the return value is "scoped" to an access into the lifetime of the original value.
 Because lifetime dependencies can only be attached to non-`Escapable` values, types that contain pointers will generally need to be non-`Escapable` in order to provide safe semantics.
 As a result, **scoped lifetime dependencies** are the only possibility whenever a non-`Escapable` value (such as `Span` or `MutableSpan`) gets its dependency from an `Escapable` value (such as `ContiguousArray` or similar container).
 
@@ -254,7 +254,7 @@ Since there can only be one mutating reference to a mutable value at any time, `
 
 ```
 extension MutableSpan {
-  @lifetime(inout self)
+  @lifetime(&self)
   mutating func extracting(_ range: Range<Int>) -> MutableSpan<Element> {
     ...
   }
@@ -280,13 +280,13 @@ func f(arg: ArgType) -> ResultType
 
 Where
 
-*  *`dependency-kind`* is one of the dependency specifiers **`borrow`**, **`inout`**, or **`copy`**, and
+*  *`dependency-kind`* is one of the dependency specifiers **`borrow`**, **`&`**, or **`copy`**, and
 * `ResultType` must be non-`Escapable`.
 
-If the `ArgType` is `Escapable`, the dependency specifier must be `borrow` or `inout` and return value will have a new scoped dependency on the argument.
+If the `ArgType` is `Escapable`, the dependency specifier must be `borrow` or `&` and return value will have a new scoped dependency on the argument.
 (This is the only possibility, since an `Escapable` value cannot have an existing lifetime dependency, so we cannot copy its lifetime dependency.)
 The specifier must further correspond to the ownership of `arg`: if `arg` has no ownership specified, or is explicitly `borrowing`, then the dependency must be `borrow`.
-On the other hand, if `arg` is `inout`, the dependency must also be `inout`.
+On the other hand, if `arg` is `inout`, the dependency must be `&`.
 (A scoped dependency cannot be formed on a `consuming` parameter.)
 
 A scoped dependency ensures that the argument will not be destroyed while the result is alive.
@@ -297,8 +297,8 @@ Also, access to the argument will be restricted for the lifetime of the result f
 * A `consuming` parameter-convention is illegal, since that ends the lifetime of the argument immediately.
 
 If the `ArgType` is non-`Escapable`, then it can have a pre-existing lifetime dependency.
-In this case, in addition to `borrow` or `inout`, a `copy` dependency-kind is allowed, to indicate that the returned value has the same dependency as the argument.
-`borrow` and `inout` dependency kinds continue to work as for `Escapable` types, and indicate that the returned value has a scoped lifetime dependency based on an access to the argument, making the returned value even further lifetime-constrained than the argument going in.
+In this case, in addition to `borrow` or `&`, a `copy` dependency-kind is allowed, to indicate that the returned value has the same dependency as the argument.
+`borrow` and `&` dependency kinds continue to work as for `Escapable` types, and indicate that the returned value has a scoped lifetime dependency based on an access to the argument, making the returned value even further lifetime-constrained than the argument going in.
 
 **Methods:** Similar rules apply to lifetime dependencies on `self` in methods.
 Given a method of this form:
@@ -309,7 +309,7 @@ Given a method of this form:
 ```
 
 The behavior depends as above on the dependency-kind and whether the defining type is `Escapable`.
-For a method of an `Escapable` type, the dependency-kind must be `borrow self` for a `borrowing` method, or `inout self` for a `mutating` method, and lifetime dependencies are not allowed on `self` in a `consuming` method.
+For a method of an `Escapable` type, the dependency-kind must be `borrow self` for a `borrowing` method, or `&self` for a `mutating` method, and lifetime dependencies are not allowed on `self` in a `consuming` method.
 For a method of a non-`Escapable` type, the dependency-kind may additionally be `copy self`.
 
 **Initializers:** An initializer can also define lifetime dependencies on one or more arguments.
@@ -566,7 +566,7 @@ func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
 /// Precondition: `dependent` depends on state that remains valid until either:
 /// (a) `source` is either destroyed if it is immutable,
 /// or (b) exclusive to `source` access ends if it is a mutable variable.
-@unsafe @lifetime(inout source)
+@unsafe @lifetime(&source)
 func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
   _ dependent: consuming T, mutating source: inout U)
   -> T {...}
@@ -674,7 +674,7 @@ This proposal adds a `@lifetime` attribute that can be applied to function, init
 >
 > *lifetime-dependence-target-name* → **`self`** | *identifier*
 >
-> *dependency-kind* → **copy** | **borrow** | **inout**
+> *dependency-kind* → **copy** | **borrow** | **&**
 
 This modifier declares a lifetime dependency for the specified target.
 If no *lifetime-dependence-target-name* is specified, then the target is the declaration's return value.
@@ -684,7 +684,7 @@ The target value must be potentially non-`Escapable`.
 Additionally, a parameter used as a target must either be an `inout` parameter or `self` in a `mutating` method.
 
 The source value of the resulting dependency can vary.
-For a `borrow` or `inout` dependency, the source value will be the named parameter or `self` directly.
+For a `borrow` or `&` dependency, the source value will be the named parameter or `self` directly.
 However, if the named parameter or `self` is non-`Escapable`, then that value will itself have an existing lifetime dependency, and a `copy` dependency will copy the source of that existing dependency.
 As with the target, a source parameter is referenced by its "internal" parameter name rather than by its argument label.
 
@@ -811,18 +811,18 @@ func reassignWithArgDependence(_ span: inout Span<Int>, _ arg: ContiguousArray<I
 
 This means that an `inout` parameter of potentially non-`Escapable` type can interact with lifetimes in three ways:
 
-- as the source of a scoped dependency, as in `@lifetime([<target>:] inout x)`
+- as the source of a scoped dependency, as in `@lifetime([<target>:] &x)`
 - as the source of a copied dependency, as in `@lifetime([<target>:] copy x)`
 - as the target of a dependency, as in `@lifetime(x: <dependency>)`
 
 so it is worth restating the behavior here to emphasize the distinctions.
-A scoped dependency `@lifetime(inout x)` indicates that the target's lifetime is constrained by exclusive access to `x`.
+A scoped dependency `@lifetime(&x)` indicates that the target's lifetime is constrained by exclusive access to `x`.
 A copied dependency `@lifetime(copy x)` indicates that the target copies its lifetime constraint from value of `x` when the callee *begins* execution.
 As the target of a dependency, `@lifetime(x: <dependency>)` indicates the lifetime constraint added to the value of `x` after the callee *ends* execution.
 
 By composition, an `inout` parameter could appear as both the source and target of a dependency, though the behavior is not useful in either case:
 
-- `@lifetime(x: inout x)` states that the value of `x` on return from the callee is dependent on exclusive access to the variable `x`.
+- `@lifetime(x: &x)` states that the value of `x` on return from the callee is dependent on exclusive access to the variable `x`.
     This would have the net effect of making the argument to `x` inaccessible for the rest of its lifetime, since it is exclusively accessed by the value inside of itself.
 - `@lifetime(x: copy x)` states that the value of `x` on return from the callee copies its dependency from the value of `x` when the function began execution, in effect stating that the lifetime dependency does not change.