Unions
Unions are discriminated (tagged) variant types. Each case has a zero-based index that serves as the wire discriminator.
Basic Syntax
union Shape { Circle(radius: f4), Rectangle(width: f4, height: f4), Triangle(a: f4, b: f4, c: f4) }
Each case is assigned a sequential index: Circle = 0, Rectangle = 1, Triangle = 2.
Shared Fields (Base Arguments)
Unions can declare shared fields that are present in every case:
union ApiResponse(requestId: u4, timestamp: datetime) { Success(data: bytes), NotFound(path: string), Error(code: i4, message: string) }
requestId and timestamp are available in all three cases.
Type Reference Cases
Cases can reference existing types instead of declaring inline fields:
msg UserData { name: string; age: u1; } msg ErrorInfo { code: i4; message: string; } union Result { UserData, ErrorInfo }
Unions with type reference cases cannot declare shared fields. Doing so triggers ION0012.
Wire Format & Discriminator
Unions are serialized as a CBOR array where the first element is the discriminator index:
// Shape.Rectangle(width: 10, height: 20) [1, 10.0, 20.0] // discriminator=1 (Rectangle), then fields // Shape.Circle(radius: 5) [0, 5.0] // discriminator=0 (Circle), then fields
Reordering union cases is a breaking change — it shifts the discriminator index. Detected by ION0028.
Generated Code
In C#, unions generate an interface marked with IIonUnion<T> and sealed classes for each case:
public interface Shape : IIonUnion<Shape> { public sealed class Circle : Shape { public float radius { get; set; } } public sealed class Rectangle : Shape { public float width { get; set; } public float height { get; set; } } }