SwiftQA Random

What are Swift concurrency isolation rules?

The core concept: isolation domains

Every piece of code belongs to exactly one isolation domain: a specific actor, the global MainActor, or “non-isolated.” The rules govern (1) what you can access synchronously vs. needing await, and (2) what’s allowed to cross domains.

Rule 1: Actor-isolated state requires being “on” that actor

actor BankAccount {
    var balance: Double = 0
    func deposit(_ amount: Double) { balance += amount }
}
await account.deposit(10) // must await from outside

Rule 2: Global actors apply the same rule to free-floating declarations

@MainActor extends actor isolation to types/functions/properties that aren’t actors themselves.

Rule 3: Isolation is inherited by default within a context

A Task { } created inside an isolated context inherits that isolation unless broken by Task.detached.

Rule 4: nonisolated opts a declaration out of its enclosing isolation

actor Logger {
    nonisolated let id = UUID()
    nonisolated func staticInfo() -> String { "Logger" }
}

Swift 6.2’s nonisolated(nonsending) additionally lets a nonisolated async function choose to stay on the caller’s isolation domain vs. @concurrent hopping to the global executor.

Rule 5: Crossing an isolation boundary requires Sendable (or sending)

class MutableBox { var value = 0 }  // not Sendable

func launch(_ box: MutableBox) {
    Task { box.value += 1 }  // ❌ error unless Sendable or `sending`
}

Rule 6: Structured concurrency ties child task isolation to the parent

async let and TaskGroup children inherit the isolation context of where they’re created.

Rule 7: Protocol conformance and isolation must agree

A method satisfying a protocol requirement must match the protocol’s isolation expectations.

The unifying model

Two enforced invariants:

  1. You can’t touch isolated mutable state without proving you’re already on that isolation domain.
  2. You can’t move a value across isolation domains without proving it’s safe to share.

What these rules explicitly do NOT cover

  • No reentrancy bugs
  • No deadlocks
  • Correct business logic

One-liner if pressed: “Swift’s isolation rules boil down to two enforced invariants: you can’t synchronously touch actor-isolated state unless you’re already on that actor, and you can’t move a value across isolation domains unless it’s Sendable or provably safe to send — everything else is about controlling where code runs and how isolation propagates through that structure.”