Files
sx/examples/0799-types-self-ref-recursive-enum-union.sx
agra d8076b9333 lang: rename signed integer types sN -> iN
Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.

Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).

Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.

zig build test: 426/426; examples suite: 595/595.
2026-06-12 09:31:53 +03:00

46 lines
1.9 KiB
Plaintext

// E6a (attempt-2) regression — RECURSIVE top-level enum/union via per-decl nominal
// identity. Three single-author shapes that reference a not-yet-interned name in a
// `*Name` field:
// * `Node` — a SELF-referential UNION (linked cells: `next: *Node`).
// * `Tree` — a SELF-referential ENUM/tagged-union (`branch: *Tree`).
// * `A`/`B` — a MUTUALLY-referential union pair (`A` holds `*B`, `B` holds `*A`).
//
// Pre-fix (eed2f99) the new per-decl register path built each enum/union body
// through the STATELESS `type_bridge` BEFORE a matching nominal slot existed, so a
// `*Name` field forward-created a STRUCT stub under `Name`; `internNamedTypeDecl`
// then refreshed that struct stub as an enum/union and tripped the kind-stability
// assert in `types.zig` `updatePreservingKey` — a hard panic (the corpus had no
// recursive enum/union, so the gate missed it). The fix adopts the forward struct
// stub IN PLACE (re-key to the real enum/union kind), mirroring how a self-ref
// struct adopts its own forward stub — so `*Node`/`*Tree`/`*B`/`*A` resolve to the
// genuine 8-byte-pointer nominal types and the recursive walks read through.
#import "modules/std.sx";
Node :: union { next: *Node; value: i32; }
Tree :: enum { leaf: i32; branch: *Tree; }
A :: union { b: *B; tag: i32; }
B :: union { a: *A; val: i32; }
main :: () -> i32 {
// Self-ref union: two-hop walk to the tail cell's value.
n2 : Node = ---;
n2.value = 7;
n1 : Node = ---;
n1.next = @n2;
n0 : Node = ---;
n0.next = @n1;
// Self-ref enum: a branch whose payload pointer derefs to a leaf.
leaf_node : Tree = .leaf(42);
root : Tree = .branch(@leaf_node);
// Mutual-ref pair: reach B's value through A's `*B`.
bv : B = ---;
bv.val = 99;
av : A = ---;
av.b = @bv;
print("union={} enum={} mutual={}\n", n0.next.*.next.*.value, root.branch.*.leaf, av.b.*.val);
0
}