Skip to main content

Phase 5. Sum types (tagged enums)

FieldValue
MEPMEP-53 §Phases
StatusLANDED
Started2026-05-28 (GMT+7)
Landed2026-05-29 07:35 (GMT+7)
Tracking issue— (umbrella)
Tracking PR#22499
Commit26217cbcec

Gate

TestPhase5Sums walks tests/transpiler3/rust/fixtures/phase05-sums/ (27 fixtures) and asserts byte-equal stdout. Coverage: tag-only variants, variants with positional fields, variants with named fields, recursive types (Tree, List), match with wildcards, match with literal patterns, match with binding patterns, match with guards.

Lowering decisions

type Shape = Circle { r: float } | Rect { w: float, h: float } | Empty

lowers to:

#[derive(Clone, Debug, PartialEq)]
enum Shape {
Circle { r: f64 },
Rect { w: f64, h: f64 },
Empty,
}

Variant constructors are emitted as Shape::Circle { r: 2.0 } (struct-like) or Shape::Cons(x, xs) (tuple-like). Match is direct:

match s {
Shape::Circle { r } => /* arm */,
Shape::Rect { w, h } => /* arm */,
Shape::Empty => /* arm */,
}

Recursive variants (Cons(int, List)) require indirection — Box<List> is wrapped around the recursive position by the lower pass when the type is self-referential.

Match decision trees are pre-built by the clower pass (Maranget 2008 algorithm) so the emitted match is exhaustive without redundant arms. The Rust compiler's own exhaustiveness check is the secondary gate.

Files changed

FilePurpose
transpiler3/rust/lower/sum.goSum type and match lowering
transpiler3/rust/lower/recursive.goBox-wrapping for self-referential variants
transpiler3/rust/build/phase05_test.go27-fixture gate
tests/transpiler3/rust/fixtures/phase05-sums/*.mochi + .out27 fixtures

Test set

  • TestPhase5Sums/<fixture> for each .mochi in the fixture directory (27 fixtures).

Closeout notes

Pattern matching against & references vs owned values is the subtle piece. When matching on xs.iter().next() (which is Option<&T>), the binding inside the variant is &Inner, but downstream code wants Inner. Phase 5 always matches on owned values (using .cloned() before match) so the binding is uniform; the colour pass in phase 6 can later promote some match scrutinees back to & form to avoid the clone.