← All daysDay 33 of 49 · Part 9: Swift concurrency
Day 33

Sendable and Swift 6 strict concurrency

These are the lesson notes for this day. Its build-along tutorial and flash cards have not been written yet.

Lesson 38

Sendable and Swift 6 strict concurrency

Sendable marks a type as safe to hand from one concurrency domain to another — between actors, or into a task. Value types made of sendable parts are sendable automatically. Classes generally are not, unless they are immutable or protect their own state. In the Swift 6 language mode the compiler rejects code that could cause a data race: passing a non-sendable value across a boundary, or touching shared mutable state from the wrong place.

How to migrate an existing codebase, in order. (1) Stay in Swift 5 language mode and set Strict Concurrency Checking to Complete, so that every problem appears as a warning rather than an error. (2) For app targets, set Default Actor Isolation to MainActor. (3) Fix the warnings by kind. Global mutable state becomes an actor or is marked @MainActor (or, as a last resort, nonisolated(unsafe)). Values that cross a boundary are made Sendable, or passed with sending. Delegate callbacks move to @MainActor or are turned into an AsyncStream. Libraries that have not been updated are imported with @preconcurrency import. (4) Switch each module to Swift 6 mode once it has no warnings left.

Exercise

Take one older target through those four steps. Keep a tally of which kind of warning came up most often. That tally is a good answer to an interview question about migration.

After this lesson you should be able to answer
  1. What does marking a type Sendable promise?
  2. Why migrate using warnings in Swift 5 mode before switching on Swift 6 mode?
  3. Name three kinds of concurrency warning and the usual fix for each.
Resources