# \[Pitch\] Non-Escapable Types and Lifetime Dependency

**URL:** <https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865>\
**Category:** Pitches\
**Created:** [February 6, 2024, 12:52am UTC](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865 "2024-02-06T00:52:52Z")\
**Posts on this page:** 1\
**Showing post:** 55

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [April 12, 2024, 7:21pm UTC](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865/55 "2024-04-12T19:21:47Z")

</div>

As review manager for these proposals, I've been reading through the discussion and review revision history to understand the discussion that has happened so far. I wanted to raise a few points for community discussion while we get this ready for review:

## Syntax revision

It appears that most of the discussion in this thread discussed a syntax model for lifetime dependencies using `borrow(x)`, `mutate(x)`, `copy(y)`, `consume(y)`, with the former two indicating a scoped dependency on an access of `x`, and the latter two indicating a dependency copied from an existing nonescaping value `y`. The current proposal has been revised to use a simpler-looking model where one syntax `dependsOn(x)` "does what you mean", forming a scoped dependency on an access of `x` when `x` is escapable or a `borrowing`/`inout` parameter, or copying the dependency from `x` if it's a nonescaping `consuming` or copyable value. `dependsOn(scoped x)` can be used to explicitly form a scoped dependency. Speaking personally, this appears to be an improvement, but it doesn't appear that this revision was discussed yet in the pitch thread, so I wanted to prompt discussion about it.

## Values of `~Escapable` type with unlimited, indefinite, and/or unknown lifetime

The proposal only tangentially discusses values of `~Escapable` type that don't have a lifetime dependency, mentioning in passing an `@_unsafeNonescapableResult` attribute without going into depth. I think this capability deserves a little more consideration, since from talking to some early adopters of this feature, it sounds like the need (or at least desire) for it comes up in a number of common scenarios. For one example, an `enum` may have some cases which are `~Escapable` but also some cases that have `Escapable`-payload or no-payload case. If we extend the standard library `Optional` and `Result` types to allow for `~Escapable` values, they would likely look like:

```swift
enum Optional<Wrapped: ~Copyable & ~Escapable>: ~Copyable, ~Escapable {
  case none, some(T)
}

enum Result<Success: ~Copyable & ~Escapable, Failure: Error>: ~Copyable, ~Escapable {
  case failure(Failure), success(Success)
}

```

When constructing an `Optional<NotEscapable>.none` or `Result<NotEscapable>.failure(error)` case, there's no lifetime to assign to the constructed value in isolation, and it wouldn't necessarily need one for safety purposes, because the given instance of the value doesn't store any state with a lifetime dependency.

Another place where indefinite lifetimes might come up arose in the pitch discussion thus far, where the question of what happens with dependencies on global variables arose. When a value has a scoped dependency on a global `let` constant, that constant lives for the duration of the process and is effectively perpetually borrowed, so one could say that values dependent on such a constant have an effectively infinite lifetime as well. This would be analogous to the `'static` lifetime in Rust.

Anecdotally, a few developers I've spoken to who've tried to early-adopt `~Escapable` types have also wanted to be able to construct a value without a lifetime constraint as a layering strategy, where a primitive private unsafe initializer takes raw unsafe pointers as a building block for the safe public API, like:

```swift
public struct Ref<T: ~Copyable>: ~Escapable {
  private var address: UnsafePointer<T>

  private init(unsafePointer: UnsafePointer<T>) -> /*what lifetime?*/ Ref<T>

  public init(borrowing value: borrowing T) -> dependsOn(value) Ref<T> {
    self.init(unsafePointer: _someWayToGetALimitedScopePointer(to: value))
  }
}

```

This use case is perhaps less essential, since an arguably safer way to layer this is to have it so that even the primitive initializer takes a phantom parameter to specify the lifetime dependency, so that it's harder to create leaky unconstrained unsafe values:

```swift
public struct Ref<T: ~Copyable>: ~Escapable {
  private var address: UnsafePointer<T>

  private init<X>(unsafePointer: UnsafePointer<T>, dependingOn dummy: borrowing X) -> dependsOn(dummy) Ref<T> { ... }

  public init(borrowing value: borrowing T) -> dependsOn(value) Ref<T> {
    self.init(unsafePointer: _someWayToGetALimitedScopePointer(to: value), dependingOn: value)
  }
}

```

The proposal might encourage this approach more explicitly as a safer way of building up nonescaping reference types from primitives. However, the cases of enum payloads and global dependencies are perfectly safe and not uncommon situations where indefinite lifetimes would be useful.

Thank you to everyone who has contributed to the discussion thus far!

---

_[View the full topic](https://forums.swift.org/t/pitch-non-escapable-types-and-lifetime-dependency/69865)._
