Files
sx/examples/comptime/expected/0646-comptime-field-reflect-tuple-array.exit
agra 8ac6c573e8 fix: comptime field reflection on tuples/arrays/vectors (issue 0195)
`field_count` / `field_name` were broken on every non-struct/enum aggregate:
`field_count(Tuple(i64, bool))` silently returned 0 (a missing `.tuple` arm in
the count switches), and `field_name(tuple/array/vector, i)` SEGFAULTED — the
LLVM backend built a zero-length `[0 x string]` name array for those kinds while
sizing the runtime GEP at the (often non-zero) member count, so the indexed load
ran past the array.

Root cause was three+ parallel switches that each had to know how to count an
aggregate's members, and disagreed: `field_count` lowering and `memberCount` had
struct/union/tagged_union/enum/array/vector but no `.tuple`; the backend's
`field_name_get` build + GEP sizing had neither `.tuple` nor `.array`/`.vector`.

Fix:
- add the `.tuple` arm to `field_count` lowering (src/ir/lower/call.zig) and
  `TypeTable.memberCount` (src/ir/types.zig; this also backs the COMPILER-API
  `type_field_count` VM reader).
- unify the LLVM backend onto the single source of truth: both
  `getOrBuildFieldNameArray` (reflection.zig) and `emitFieldNameGet`'s GEP sizing
  (ops.zig) now derive from `memberCount` / `memberName`, so the name-array
  length and the GEP array type can never diverge again — for any kind. A member
  with no name (positional-tuple / array / vector element) reflects as "" (one
  slot per member, always in-bounds); named-tuple elements recover their labels.

The array/vector clone was surfaced by adversarial review of the tuple-only fix.

Regression: examples/comptime/0646-comptime-field-reflect-tuple-array.sx exercises
field_count/field_name/field_type over struct, enum, positional + named tuple,
array, and vector. Full suite green (818/0). Unblocks the `race` synthesis, which
must reflect a named tuple's labels + element types.
2026-06-26 12:28:09 +03:00

2 B