Skip to content

Commit e814e62

Browse files
authored
Merge pull request #7 from atrick/lifetime-dependency
Added future directions: Function type syntax and closures
2 parents 25f30b3 + e1d364e commit e814e62

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

proposals/NNNN-lifetime-dependency.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,90 @@ func f(a: A, b: B) -> (dependsOn(a) C, B)
952952
```
953953
We expect to address this in the near future in a separate proposal.
954954

955+
### Function type syntax
956+
957+
A function that returns a nonescapable type cannot currently be passed as a nonescaping closure because its dependence information would be lost.
958+
959+
```swift
960+
func f(arg: ArgType) -> dependsOn(arg) NEType
961+
962+
func g1(closure: (ArgType) -> NEType)
963+
964+
{
965+
g1(closure: f) // 🛑 ERROR: function type mismatch
966+
}
967+
```
968+
969+
To address this shortcoming, we plan to extend the `dependsOn(...)` modifier for use in function types. Since function
970+
types have no parameter names, the parameter position will be identified by an integer literal:
971+
972+
```swift
973+
func g2(closure: (ArgType) -> dependsOn(0) NE)
974+
975+
{
976+
g2(closure: f) // ✅ OK
977+
}
978+
```
979+
980+
The parameter index syntax is consistent with how dependencies are already represented internally and in mangled names.
981+
982+
We expect most closures that return nonescapable types to be dependent on the closure context rather than a closure
983+
parameter--this will be the normal case for passing methods as nonescaping closures. A closure context dependence will
984+
not affect the spelling of the function type.
985+
986+
### Lifetime dependence for closures
987+
988+
In "Function type syntax", we propose that function types can have explicit `dependsOn` modifiers. When a function type
989+
returns a nonescapable value but has no explicit `dependsOn` modifier, we plan to infer a dependence on the closure
990+
context:
991+
992+
```swift
993+
func g1(closure: () -> NEType) // Inferred: NEType depends on 'closure'
994+
```
995+
996+
For closure declarations, lifetime dependencies can be inferred on the combined list of captures and closure parameters
997+
following the same rule as free standing functions. We can infer a lifetime dependence if the closure's return value is
998+
nonescapable, and exactly one closure capture or closure parameter satisfies any of the following:
999+
1000+
- is nonescapable, or
1001+
- is non-BitwiseCopyable and has an explicit `borrowing`, or `inout` convention
1002+
1003+
A dependence can be inferred on a closure capture as follows:
1004+
1005+
```swift
1006+
func f(arg: borrowing ArgType) -> dependsOn(arg) NEType
1007+
1008+
func foo(source: borrowing ArgType) {
1009+
g1 { f(arg: source) } // ✅ Inferred: 'closure' result depends on captured 'source'
1010+
}
1011+
```
1012+
1013+
An explicit dependence on a closure capture can be spelled:
1014+
1015+
```swift
1016+
func foo(source: borrowing ArgType) {
1017+
g1 { () -> dependsOn(source) NEType in f(arg: source) }
1018+
}
1019+
```
1020+
1021+
Similarly, a dependence can be inferred on a closure parameter:
1022+
1023+
```swift
1024+
func g2(closure: (borrowing ArgType) -> dependsOn(0) NEType)
1025+
1026+
{
1027+
g2 { (source: borrowing ArgType) in f(arg: source) } // ✅ Inferred: 'closure' result depends on 'source' parameter
1028+
}
1029+
```
1030+
1031+
An explicit dependence on a closure parameter can be spelled:
1032+
1033+
```swift
1034+
{
1035+
g2 { (source: borrowing ArgType) -> dependsOn(source) NEType in f(arg: source) } // ✅ Inferred: 'closure' result depends on 'source' parameter
1036+
}
1037+
```
1038+
9551039
### Component lifetime
9561040

9571041
In the current design, aggregating multiple values merges their scopes.

0 commit comments

Comments
 (0)