Skip to content

Instantly share code, notes, and snippets.

@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.

<

Constrain implicit raw pointer conversion to trivial values

Introduction

Swift supports implicit inout conversion to unsafe pointers. A mutable variable can be passed inout to a function that receives an unsafe pointer to the value. According to the normal rules for pointer conversion, this naturally extends to raw pointers. Raw pointers allow the pointer-taking function to operate directly on the value's bytes.

func readBytes(_ pointer: UnsafeRawPointer) {
  assert(pointer.load(as: UInt16.self) == 0xaaaa)
}
@atrick
atrick / 2022-07-borrowed-value.md
Last active July 27, 2022 01:04
BorrowedValue pre-pitch

BorrowedValue pitch

Introduction

Adding control over value ownership to Swift requires the coordination of multiple language features. This proposal focuses on the specific problem of composing aggregates from "shared" values. A "shared borrow" provides read-only access to a value within a designated scope. This allows APIs to view the contents of a value without taking ownership of it.

Let's define "shared borrowing" as initializing a non-owned variable with the value from another variable without making a copy. To be concise, we'll just call this "borrowing" from here on. Consider passing an argument to a non-consuming parameter (this is the default ownership convention):

func nonConsuming<T>(t: T)
@atrick
atrick / 2022-04-iterative-reachability.md
Last active May 5, 2022 01:06
Iterative Backward Reachability

Iterative Backward Reachability

This should replace the current non-iterative Reachability. The current non-iterative algorithm would only make sense when uses are post-dominating and we change it to propagate in DFS RPO order. But this algorithm should very seldom need to iterate anyway. So we should probably use it instead.

Input:

  • dominating def

  • uses (gens) - during initialization only

SIL Opaque Values

Introduction

A SIL type is either loadable or address-only. A loadable type is one whose object size and layout can be determined by the compiler and whose values are not "pinned" to a memory address. Types are most commonly address-only because their layout is opaque by abstraction. Generic type parameters are address-only because their concrete type not statically identified. Resilient types are

Exclusivity Enforcement in Swift 5

The Swift 5 release enables runtime checking of "Exclusive Access to Memory" by default in Release builds. Previously, these runtime checks were only enabled in Debug builds. In this post, I'll explain what this change means for Swift developers and why it is essential to Swift's strategy for safety and performance.

Background

SE-0184 Part 2 (recomend splitting into a follow-up proposal): Buffer Full vs. Partial Initialization.

Buffer Memory State

struct UnsafeMutableBufferPointer<Element> 
{
    func initialize<S : Sequence>(from: S) -> (S.Iterator, Index) where S.Element == Element

// Amended: Remove the `at` label on all buffer APIs. Only support full initialization/assignment/deinitialization.

Analyzing dispatch performance

When it comes to resilient performance we need to prioritize future flexibility and ABI simplicity over perceived performance advantages. Being able to react to future performance issues that arise with specific apps is far more important than benchmarking. Time not spent implementing complex ABI mechanisms is time that will be spent optimizing more critical performance areas.

It's easy to say we should simply measure performance and let the data