Skip to content

Commit f16293c

Browse files
authored
Merge pull request #10 from atrick/lifetime-dependency
Fix inference rules to be sequenced.
2 parents 4152b2e + 0a4392f commit f16293c

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

proposals/NNNN-lifetime-dependency.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ This is a key requirement for the `Span` type (previously called `BufferView`) b
4848
- New alternative considered: where clause
4949
- Simplified implicit lifetime dependencies and added same-type rule
5050

51+
**Edited** (Aug 13, 2024)
52+
- Revised the same-type rule
53+
5154
#### See Also
5255

5356
* [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:
302305

303306
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.
304307

308+
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.
309+
305310
### Dependent parameters
306311

307312
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
668673

669674
### Inference Rules
670675

671-
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:
676+
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:
672677

673-
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.
678+
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.
674679

675-
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.
680+
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.
676681

677682
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.
678683

@@ -681,16 +686,18 @@ For all inference rules, the type of dependence is the same as an explicit `depe
681686
**In no other case** will a function, method, or initializer implicitly gain a lifetime dependency.
682687
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.
683688

684-
We infer dependencies according to all applicable rules. Here, both rule #1 and #2 apply:
689+
Consider an example that matches both rule #1 and #2:
685690

686691
```
687692
struct NE: ~Escapable { ... }
688693
struct E {
689-
func foo(ne: NE) -> /* dependsOn(self, ne) */ NE
694+
func foo(ne: NE) -> /* dependsOn(ne) */ NE
690695
}
691696
```
692697

693-
Here, both rule #2 and #3 apply:
698+
`foo` will not depend on self because rule #1 takes precedence over rule #2.
699+
700+
In this example, both rule #2 and #3 match but are simply redundant:
694701

695702
```
696703
struct NE {
@@ -916,7 +923,7 @@ func foo(...)
916923

917924
```
918925
@lifetime(copy arg)
919-
func foo(arg: Arg1) -> R {}
926+
func foo(label arg: Arg1) -> R {}
920927
```
921928

922929
The `.component` qualifier is only relevant once we have component lifetimes. See the "Component lifetime" section below.

0 commit comments

Comments
 (0)