Skip to content

Commit a502076

Browse files
committed
s/@dependsOn/dependsOn/ to match implementation
1 parent f648b02 commit a502076

File tree

1 file changed

+30
-28
lines changed

1 file changed

+30
-28
lines changed

proposals/NNNN-lifetime-dependency.md

+30-28
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ To reduce the burden of manually adding such annotations, we also propose inferr
1414

1515
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.
1616

17+
**Edited** (Apr 12, 2024): Changed `@dependsOn` to `dependsOn` to match the current implementation.
18+
1719
#### See Also
1820

1921
* **TODO**: **** Forum thread discussing this proposal
@@ -97,16 +99,16 @@ Our proposal would allow you to declare an `array.bufferReference()` method as f
9799

98100
```swift
99101
extension Array {
100-
borrowing func bufferReference() -> @dependsOn(self) BufferReference<Element> {
102+
borrowing func bufferReference() -> dependsOn(self) BufferReference<Element> {
101103
... construct a BufferReference ...
102104
}
103105
}
104106
```
105107

106-
The annotation `@dependsOn(self)` here indicates that the returned value must not outlive the array that produced it.
108+
The annotation `dependsOn(self)` here indicates that the returned value must not outlive the array that produced it.
107109
Conceptually, it is a continuation of the function's borrowing access:
108110
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.
109-
Specifically, the `@dependsOn(self)` annotation in this example informs the compiler that:
111+
Specifically, the `dependsOn(self)` annotation in this example informs the compiler that:
110112

111113
* The array must not be destroyed until after the `BufferReference<Element>` is destroyed.
112114
This ensures that use-after-free cannot occur.
@@ -119,13 +121,13 @@ Let’s consider another hypothetical type: a `MutatingBufferReference<T>` type
119121
Here's one way such a value might be produced:
120122

121123
```swift
122-
func mutatingBufferReference(to: inout Array, count: Int) -> @dependsOn(to) MutatingBufferReference<Element> {
124+
func mutatingBufferReference(to: inout Array, count: Int) -> dependsOn(to) MutatingBufferReference<Element> {
123125
... construct a MutatingBufferReference ...
124126
}
125127
```
126128

127129
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.
128-
The `@dependsOn(to)` annotation indicates that the returned value depends on the argument named `to`.
130+
The `dependsOn(to)` annotation indicates that the returned value depends on the argument named `to`.
129131
Because `count` is not mentioned in the lifetime dependency, that argument does not participate.
130132
Similar to the previous example:
131133

@@ -143,7 +145,7 @@ Here's a typical example that constructs a new `BufferReference` from an existin
143145
```swift
144146
struct BufferReference<T>: ~Escapable {
145147
...
146-
consuming func drop(_: Int) -> @dependsOn(self) BufferReference<T> { ... }
148+
consuming func drop(_: Int) -> dependsOn(self) BufferReference<T> { ... }
147149
...
148150
}
149151
```
@@ -176,7 +178,7 @@ The syntax is somewhat different for functions and methods, though the basic rul
176178
**Functions:** A simple function with an explicit lifetime dependency annotation generally takes this form:
177179

178180
```swift
179-
func f(arg: <parameter-convention> ArgType) -> @dependsOn(arg) ResultType
181+
func f(arg: <parameter-convention> ArgType) -> dependsOn(arg) ResultType
180182
```
181183

182184
Where
@@ -195,21 +197,21 @@ Also, access to the argument will be restricted for the lifetime of the result f
195197
* A `consuming` parameter-convention is illegal, since that ends the lifetime of the argument immediately.
196198

197199
If the `ArgType` is nonescapable, then it can have a pre-existing lifetime dependency.
198-
In this case, the semantics of `@dependsOn()` are slightly different:
200+
In this case, the semantics of `dependsOn()` are slightly different:
199201
* A `consuming` parameter-convention will copy the lifetime dependency from the argument to the result
200202
* A `borrowing` or `inout` parameter-convention can either copy the lifetime dependency or create a new scoped lifetime dependency.
201203
In this case, for reasons explained earlier, we default to copying the lifetime dependency.
202204
If a scoped lifetime dependency is needed, it can be explicitly requested by adding the `scoped` keyword:
203205

204206
```swift
205-
func f(arg: borrowing ArgType) -> @dependsOn(scoped arg) ResultType
207+
func f(arg: borrowing ArgType) -> dependsOn(scoped arg) ResultType
206208
```
207209

208210
**Methods:** Similar rules apply to `self` lifetime dependencies on methods.
209211
Given a method of this form:
210212

211213
```swift
212-
<mutation-modifier> func method(... args ...) -> @dependsOn(self) ResultType
214+
<mutation-modifier> func method(... args ...) -> dependsOn(self) ResultType
213215
```
214216

215217
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
219221
by using the convention that initializers can be viewed as functions that return `Self`:
220222

221223
```swift
222-
init(arg: <parameter-convention> ArgType) -> @dependsOn(arg) Self
224+
init(arg: <parameter-convention> ArgType) -> dependsOn(arg) Self
223225
```
224226

225227
### Implicit Lifetime Dependencies
@@ -234,22 +236,22 @@ As above, the details vary depending on whether `self` is escapable or nonescapa
234236
```swift
235237
struct NonescapableType: ~Escapable { ... }
236238
struct EscStruct {
237-
func f1(...) -> /* @dependsOn(self) */ NonescapableType
238-
borrowing func f2(...) -> /* @dependsOn(self) */ NonescapableType
239-
mutating func f3(...) -> /* @dependsOn(self) */ NonescapableType
239+
func f1(...) -> /* dependsOn(self) */ NonescapableType
240+
borrowing func f2(...) -> /* dependsOn(self) */ NonescapableType
241+
mutating func f3(...) -> /* dependsOn(self) */ NonescapableType
240242

241243
// 🛑 Error: there is no valid lifetime dependency for
242244
// a consuming method on an `Escapable` type
243245
consuming func f4(...) -> NonescapableType
244246
}
245247

246248
struct NEStruct: ~Escapable {
247-
func f1(...) -> /* @dependsOn(self) */ NonescapableType
248-
borrowing func f2(...) -> /* @dependsOn(self) */ NonescapableType
249-
mutating func f3(...) -> /* @dependsOn(self) */ NonescapableType
249+
func f1(...) -> /* dependsOn(self) */ NonescapableType
250+
borrowing func f2(...) -> /* dependsOn(self) */ NonescapableType
251+
mutating func f3(...) -> /* dependsOn(self) */ NonescapableType
250252

251253
// Note: A copied lifetime dependency is legal here
252-
consuming func f4(...) -> /* @dependsOn(self) */ NonescapableType
254+
consuming func f4(...) -> /* dependsOn(self) */ NonescapableType
253255
}
254256
```
255257

@@ -260,10 +262,10 @@ For example:
260262
struct NEType: ~Escapable { ... }
261263

262264
// If there is only one argument with an explicit parameter convention:
263-
func f(..., arg1: borrowing Type1, ...) -> /* @dependsOn(arg1) */ NEType
265+
func f(..., arg1: borrowing Type1, ...) -> /* dependsOn(arg1) */ NEType
264266

265267
// Or there is only one argument that is `~Escapable`:
266-
func g(..., arg2: NEType, ...) -> /* @dependsOn(arg2) */ NEType
268+
func g(..., arg2: NEType, ...) -> /* dependsOn(arg2) */ NEType
267269

268270
// If there are multiple possible arguments that we might depend
269271
// on, we require an explicit dependency:
@@ -312,7 +314,7 @@ This modifies *function-result* in the Swift grammar as follows:
312314
> *function-signature**parameter-clause* **`async`***?* **`rethrows`** *function-result**?* \
313315
> *function-result***`->`** *attributes?* *lifetime-modifiers?* *type* \
314316
> *lifetime-modifiers***`->`** *lifetime-modifier* *lifetime-modifiers?* \
315-
> *lifetime-modifier***`->`** **`@dependsOn`** **`(`** *lifetime-dependent* **`)`** \
317+
> *lifetime-modifier***`->`** **`dependsOn`** **`(`** *lifetime-dependent* **`)`** \
316318
> *lifetime-dependent***`->`** **`self`** | *local-parameter-name* | **`scoped self`** | **`scoped`** *local-parameter-name*
317319
>
318320
@@ -356,8 +358,8 @@ The return type must be exactly the token `Self` or the token sequence `Self?` i
356358

357359
```swift
358360
struct S {
359-
init(arg1: Type1) -> @dependsOn(arg1) Self
360-
init?(arg2: Type2) -> @dependsOn(arg2) Self?
361+
init(arg1: Type1) -> dependsOn(arg1) Self
362+
init?(arg2: Type2) -> dependsOn(arg2) Self?
361363
}
362364
```
363365

@@ -440,11 +442,11 @@ The notation for an explicit lifetime dependency on a property might look like t
440442

441443
```swift
442444
struct Container {
443-
var view: @dependsOn(self) ReturnType { get }
445+
var view: dependsOn(self) ReturnType { get }
444446
}
445447

446448
struct Type1: ~Escapable {
447-
var childView: @dependsOn(self) Type1 { get }
449+
var childView: dependsOn(self) Type1 { get }
448450
}
449451
```
450452

@@ -464,7 +466,7 @@ A caller may need assurance that a callee will honor a lifetime dependency betwe
464466
For example, if a function is going to destroy a container and a reference to that container in the process of computing some result,
465467
it needs to guarantee that the reference is destroyed before the container:
466468
```swift
467-
func f(container: consuming ContainerType, ref: @dependsOn(container) consuming RefType) -> ResultType
469+
func f(container: consuming ContainerType, ref: dependsOn(container) consuming RefType) -> ResultType
468470
```
469471

470472
#### Lifetime Dependencies for Tuples
@@ -481,7 +483,7 @@ We expect to address this in the near future in a separate proposal.
481483
It should be possible to return containers with collections of lifetime-constrained elements.
482484
For example, a container may want to return a partition of its contents:
483485
```swift
484-
borrowing func chunks(n: Int) -> @dependsOn(self) SomeList<@dependsOn(self) StorageView<UInt8>>
486+
borrowing func chunks(n: Int) -> dependsOn(self) SomeList<dependsOn(self) StorageView<UInt8>>
485487
```
486488
We're actively looking into ways to support these more involved cases and expect to address this in a future proposal.
487489

@@ -491,7 +493,7 @@ Internally, the implementation records dependencies based on the parameter index
491493
This could be exposed as an alternate spelling if there were sufficient demand.
492494

493495
```swift
494-
func f(arg1: Type1, arg2: Type2, arg3: Type3) -> @dependsOn(0) ReturnType
496+
func f(arg1: Type1, arg2: Type2, arg3: Type3) -> dependsOn(0) ReturnType
495497
```
496498

497499
## Acknowledgements

0 commit comments

Comments
 (0)