5.10 · What property wrappers, result builders, async and throws compile to

Language features that look like magic are rewrites: hidden storage, calls to builder methods, a changed calling convention and a branch on an error register.

Mental model. Each feature is lowered to something ordinary. Seeing the lowered form removes most of the mystery (and explains the costs).

Sugar that rewrites code

Property wrappers and result builders.

  1. What does the compiler turn a property wrapper into: what storage exists, what are $name and _name, and what does it cost? 5.10.1 · L5
    A property wrapper is a rewrite. For @Clamped var n = 5 the compiler synthesises a private stored property _n of the wrapper type, and turns n into a computed…
  2. What does the compiler do with the statements inside a result builder body, in what order do the builder methods run, and why does it affect type checking? 5.10.2 · L5
    A result builder rewrites a block of statements, with no explicit return, into calls on the builder type. Each expression statement is passed through…

Effects in the calling convention

async and throws.

  1. How is an async function different in compiled code, what does await compile to, and what is a hop_to_executor? 5.10.3 · L5
    An async function gets a different calling convention: the SIL type is @convention(thin) @async () -> Int, and the function receives a hidden async context…
  2. How is throws implemented: is it like C++ exceptions, what does try compile to, and what does it cost? 5.10.4 · L5
    Swift errors are ordinary return values, not unwinding exceptions. A throwing function has an extra result channel in its type, visible in SIL as (Int, @error…

More in Compiler & language internals