You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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).
Here, the *lifetime-dependency* argument to the lifetime modifier must be one of the following:
319
+
The *lifetime-dependent* argument to the lifetime modifier is one of the following:
293
320
294
321
**local-parameter-name*: the local name of one of the function parameters, or
295
322
* the token **`self`**, or
296
323
* either of the above preceded by the **`scoped`** keyword
297
324
325
+
This modifier creates a lifetime dependency with the return value used as the dependent value.
326
+
The return value must be nonescapable.
327
+
328
+
The source value of the resulting dependency can vary.
329
+
In some cases, the source value will be the named parameter or `self` directly.
330
+
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.
331
+
332
+
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.
333
+
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:
334
+
335
+
| mutation modifier | argument type | without `scoped`| with `scoped`|
Two observations may help in understanding the table above:
345
+
* An escapable argument cannot have a pre-existing lifetime dependency, so copying is never possible in those cases.
346
+
* 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.
347
+
348
+
**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.
349
+
298
350
#### Initializers
299
351
300
-
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.
301
-
We propose allowing initializers to write out an explicit return clause for this case.
352
+
Since nonescapable values cannot be returned without a lifetime dependency,
353
+
initializers for such types must specify a lifetime dependency on one or more arguments.
354
+
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.
302
355
The return type must be exactly the token `Self` or the token sequence `Self?` in the case of a failable initializer:
The implications of mutation modifiers and argument type on the resulting lifetime dependency exactly follow the rules above for functions and methods.
372
+
318
373
### Inference Rules
319
374
320
375
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
326
381
327
382
* the return type is `~Escapable`,
328
383
* there is exactly one argument that satisfies any of the following:
329
-
** is either `~Copyable` or `~Escapable`
330
-
** is `Escapable` and `Copyable` and has an explicit `borrowing`, `consuming`, or `inout` convention specified
384
+
- is either `~Copyable` or `~Escapable`
385
+
- has an explicit `borrowing`, `consuming`, or `inout` convention specified
331
386
332
387
In this case, the compiler will infer a dependency on the unique argument identified by this last set of conditions.
333
388
334
389
**In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
335
390
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.
336
391
337
-
### Semantics
338
-
339
-
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.
340
-
341
-
When the dependency involves a function, method, or initializer argument,
342
-
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.
343
-
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.
344
-
Further, the compiler will issue diagnostics if these requirements cannot be satisfied:
345
-
346
-
* The return value must be destroyed before the source value.
347
-
This can be obstructed if there are other factors (such as nested scopes, function returns, or closure captures) that contradict the lifetime dependency.
348
-
* For a borrowing argument, the source value cannot be mutated before the return value is destroyed.
349
-
* For an inout argument, the source value is accessed or mutated before the return value is destroyed.
350
-
351
-
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`.
352
-
353
-
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`.
354
-
In this case, we’ll refer to the argument or `self` as the *original* value.
355
-
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.
356
-
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.
357
-
358
-
### Relation to ~Escapable
359
-
360
-
The lifetime dependencies described in this document can be applied only to `~Escapable` return values.
361
-
Further, any return value that is `~Escapable` must have a lifetime dependency.
362
-
In particular, this implies that the initializer for a non-escapable type must have at least one argument.
363
-
364
-
```swift
365
-
structS: ~Escapable {
366
-
init() {} // 🛑 Error: ~Escapable return type must have lifetime dependency
367
-
}
368
-
```
369
-
370
392
## Source compatibility
371
393
372
394
Everything discussed here is additive to the existing Swift grammar and type system.
373
395
It has no effect on existing code.
374
396
375
-
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`.
376
-
This ambiguity can be fully resolved in the parser by looking for an open parenthesis `(` after the `dependsOn` token.
377
-
378
397
## Effect on ABI stability
379
398
380
399
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.
0 commit comments