Skip to content

Instantly share code, notes, and snippets.

@atrick
atrick / 2024-04-indefinite-lifetimes.md
Last active April 25, 2024 21:09
Indefinite lifetimes

Indefinite lifetimes

Immortal lifetimes

In some cases, a nonescapable value must be constructed without any object that can stand in as the source of a dependence. Consider extending the standard library Optional or Result types to be conditionally escapable:

enum Optional<Wrapped: ~Escapable>: ~Escapable {
  case none, some(Wrapped)
}
@atrick
atrick / 2024-04-bitwisecopyable-dependence.md
Last active April 23, 2024 15:49
Using the `@_unsafeNonescapableResult` function attribute

Using the @_unsafeNonescapableResult function attribute

Indeterminate lifetimes

In some cases, a nonescapable value must be constructed without any object that can stand in as the source of a dependence. Consider extending the standard library Optional or Result types to be conditionally escapable:

enum Optional<Wrapped: ~Escapable>: ~Escapable {
  case none, some(Wrapped)
}
@atrick
atrick / 2024-generic-lifetimes.md
Last active February 29, 2024 00:34
Lifetime dependence with generic types

Lifetime dependence with generic types

Conditionally nonescapable types

The current design of lifetimes relies on "value lifetimes" and "conditionally non-escapable types". Values of Escapable type have no lifetime scope. Values of ~Escapable type have a single lifetime scope. A nonescapable value cannot live beyond the current scope unless the scope's function interface provides value-based lifetime propagation via @dependsOn annotations.

E ≡ some T
NE ≡ some T: ~Escapable

Without a lifetime annotation, functions cannot return nonescapable values:

@atrick
atrick / 2022-variable-lifetime-proposal.md
Last active May 22, 2023 19:02
Swift variable lifetimes

Optimization rules governing the lifetime of Swift variables

Introduction

The combination of automatic reference counting (ARC) and synchronous deinitializers presents a substantial challenge for an optimizing compiler unique to Swift. The Swift 5.7 compiler follows new rules for when optimization is allowed to end the lifetime of variables. The result is more predictable, user-friendly, and performant ARC behavior.

To enforce the new rules, the compiler adopted a new internal representation that tracks the lexical scope of each variable. This involved updating existing optimizations and implementing several new optimizations. Now, all areas of the compiler follow the same, consistent, well-defined rules, making it possible to reason about its behavior for the first time.

The most common programming patterns that depend on extended variable lifetimes are now safe without requiring programmers to explicitly use withExtendedLifetime(). This protec

@atrick
atrick / 2022-12-dependent-properties.md
Last active April 3, 2023 21:52
Dependent properties

Lifetime-dependent properties

Introduction

A lifetime-dependent property (or "dependent property") is a struct or class property whose value can only be accessed within an enclosing scope, during which the parent object cannot be deinitialized. A dependent property can provide a lightweight "view" of its parent object's underlying storage through an alternate type. This proposal focuses on the problem of returning the view object as a property of its "container". The author of the view type still bears responsibility for other aspects of safety. The Future Directions sections cover additional features needed to support development of safe view types.

Motivation

A container data type often needs to provide limited access to its underlying storage to a more general purpose API that consumes the data but is otherwise independent of the data type. In Swift, this is typically done by having the container provide a "slice" that conforms to the Collection protocol. Since slices depend on their container's

@atrick
atrick / 2022-05-BufferView.md
Last active March 28, 2023 18:07
BufferView Proposal

BufferView Proposal

Introduction

Building Swift system APIs requires a common data type for efficiently viewing contiguous memory as a series of typed elements. This proposal introduces BufferView<T> and MutableBufferView<T> as lowest-common-denominator types that can be used across many low-level APIs without sacrificing safety, efficiency, and generality.

The closest alternative, UnsafeBufferPointer<T>, is not ideal for several reasons:

  • it is ownership unsafe, leading to use-after-free security holes
@atrick
atrick / 2023-implicit-raw-bitwise.md
Last active February 22, 2023 22:38
Constrain implicit raw pointer conversion to bitwise-copyable values

Constrain implicit raw pointer conversion to bitwise-copyable values

Introduction

This proposal adds restrictions on implicit casts to unsafe pointers. It allows implicit casts only when the source value is either "bitwise copyable" or has custom support for unsafe pointer casts. A type is bitwise copyable if copying a value of that type requires nothing more than copying each bit in its representation (i.e. memcpy). Bitwise copyable types do not require deinitialization. Notably, bitwise copyable types cannot contain object references. Raw pointers are primarily intended for use with bitwise-copyable types because it is extremely difficult and dangerous to work with raw bytes in the presence of object references.

The implicit raw pointer casts that we want to prohibit commonly happen accidentally, without any source-level indication of unsafety. They nonetheless pose a serious safety and security concern. They are a common source of programming mistakes leading to runtime crashes but have no discer

Non-escaping view proposal

Introduction

A data type often needs to provide limited access to its underlying data without copying the data. That is typically done either with a "slice" that retains a reference to the original storage, or with an unsafe pointer into the storage.

Consider slicing: return array[range]

This approach is limited because slices only work safely with reference counted storage. Slices may arbitrarily extend the original lifetime, which is sometimes unacceptable. And, finally, by retaining a reference, they prevent mutation of copy-on-write containers. So slices can't be used to mutate collection types that have value semantics.

@atrick
atrick / 2022-07-ownership-types.md
Last active November 2, 2022 21:41
Ownership Types Survey (Pre-Pitch)

A survey of proposed ownership types

This document identifies several potential type constraints related to value ownership and lifetime in Swift and explains those constraints relate to each other. They have not yet been formally proposed. This is only a straw-man. The goal of giving these constraints a name and gathering them all in one place is at least twofold. First, we gain a clear understanding of how to structure the internals of the compiler. Second, as we propose language features, we can refer to dependent features and understand how the individual proposal will fit into cohesive programming model. The goal is not to surface each constraint identified here as separate knob in the language. We expressly want to avoid making Swift a language of annotations. But the only way we can minimize the impact on the programming model is by first seeing the landscape of features that we want to cover. Naturally, any new annotation will be justified before formally proposing an addition to the language.

<