Baton

Why it is shaped this way

A format is per emitter

Status: accepted, 2026-10-07; amended 2026-10-08, the number before a first release. Serves The compiler decides. Built as decided: nothing moves. Reopen if the plan IR is ever written out and read as data by something other than the compiler.

Status: accepted, 2026-10-07; amended 2026-10-08, the number before a first release. Serves The compiler decides. Built as decided: nothing moves. Reopen if the plan IR is ever written out and read as data by something other than the compiler.

Context#

What generated Swift names in the Swift runtime is fenced by one number. compiler/src/emit.rs declares pub const FORMAT: u32 = 16; generated code writes static let format = Baton.Format16.self in its Types enum; swift/Sources/Baton/Plan.swift declares Format16 and keeps every earlier marker unavailable, with a message. CLAUDE.md states the rule: a change to what generated code names raises the number on both sides in one commit. Nothing says what the number means for a second runtime.

Decision#

  • A format is per emitter. The Kotlin emitter gets its own number and its own fence, enforced the way its language allows.

  • The plan IR between the emitters is not serialized and carries no number.

  • The two emitters change together when the plan's shape changes, and apart when one language's interface does.

  • A format's number is raised from the emitter's first release on. Before it, nothing generated by a released compiler can meet the runtime, so generated code and runtime move together under the first number: the Kotlin format stays 1 while the Kotlin runtime is built, and goes to 2 with the first change after the Kotlin runtime is first released.

Evidence#

  • The compiler and the runtime as built, by reading: FORMAT in compiler/src/emit.rs; the line that writes the marker in compiler/src/emit/shared.rs, and the same line in the golden compiler/src/tests/goldens/Baton.baton.swift; the markers in swift/Sources/Baton/Plan.swift, from format 1 to the available Format16.
  • What the fence guards is one language's interface: the messages on the unavailable markers name changes to Swift's generated code, such as a schema enum reading as the Swift enum generated for it.

Not chosen#

  • One number shared by both emitters: a Swift-only interface change would raise Kotlin's number for nothing, and the reverse.
  • A versioned IR: nothing reads it as data.