Skip to content

Commit de45422

Browse files
committed
New example: Escapable properties in a nonescapable type
1 parent 02fc95a commit de45422

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

proposals/NNNN-lifetime-dependency.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -734,11 +734,11 @@ First, let's add a mutable method to `Span`:
734734

735735
```swift
736736
extension Span {
737-
mutating func droppingPrefix(length: Int) -> /* dependsOn(self) */ Span<T> {
738-
let result = Span(base: base, count: length)
737+
mutating func removePrefix(length: Int) -> /* dependsOn(self) */ Span<T> {
738+
let prefix = Span(base: base, count: length)
739739
self.base += length
740740
self.count -= length
741-
return result
741+
return prefix
742742
}
743743
}
744744
```
@@ -807,6 +807,29 @@ do {
807807
parse(span) // 🛑 Error: 'span' escapes the scope of 'a2'
808808
```
809809

810+
#### Escapable properties in a nonescapable type
811+
812+
An escapable type inevitably contains nonescapable properties. In our `Span` example, the `base` pointer and `count`
813+
length are both escapable. Accessing an escapable property drops the dependence:
814+
815+
```swift
816+
let pointer: UnsafePointer<T>
817+
do {
818+
let span = Span(unsafeBaseAddress: pointer, count: 1)
819+
pointer = span.base
820+
}
821+
_ = pointer // ✅ OK: pointer has no lifetime dependence
822+
```
823+
824+
Internal mutation of a nonescapable type does not create any new dependence and does not require any annotation:
825+
826+
```swift
827+
mutating /* dependsOn(self: self) */ func skipPrefix(length: Int) {
828+
self.base += length // ✅ OK: assigns `base` to a copy of the temporary value
829+
self.count -= length // ✅ OK: assigns `count` to a copy of the temporary value
830+
}
831+
```
832+
810833
## Source compatibility
811834

812835
Everything discussed here is additive to the existing Swift grammar and type system.

0 commit comments

Comments
 (0)