feat(metatype): widen type_info/define to struct types

TypeInfo gains a `struct(StructInfo) variant (StructField{name,type});
the metatype system now reflects AND constructs structs, not just enums.

- meta.sx: StructField / StructInfo / `struct TypeInfo variant.
- interp: reflectTypeInfo builds .struct (tag 1) for a source @"struct";
  define dispatches on the TypeInfo tag (defineType) -> defineEnum (0) /
  defineStruct (1). defineStruct mirrors defineEnum (dup-field-name check
  included) but completes the declare slot AS a struct via replaceKeyedInfo
  (a kind change re-keys the intern map; updatePreservingKey asserts no
  key change, true only for the enum path).
- call.zig: the lower-time type_info guard now admits @"struct".

define(declare("P"), .struct(.{ fields = .[ … ] })) builds a struct, and
define(declare("C"), type_info(SrcStruct)) round-trips one. Suite green
(682); enum path (0619) unchanged.
This commit is contained in:
agra
2026-06-17 06:54:17 +03:00
parent afb1fee252
commit aaac019715
3 changed files with 121 additions and 19 deletions

View File

@@ -1731,16 +1731,15 @@ pub fn tryLowerReflectionCall(self: *Lowering, name: []const u8, c: *const ast.C
return Ref.none;
};
const t = self.resolveTypeArg(c.args[0]);
// Only enum / tagged-union reflection ships today (the symmetric
// inverse of `define`, which builds tagged-unions). A loud, well-
// spanned reject here beats a deferred interp bail; struct/tuple
// widening lands later.
// Enum / tagged-union and struct reflection ship today (the symmetric
// inverse of `define`, which builds those kinds). A loud, well-spanned
// reject here beats a deferred interp bail; tuple widening lands later.
const reflectable = !t.isBuiltin() and switch (self.module.types.get(t)) {
.@"enum", .tagged_union => true,
.@"enum", .tagged_union, .@"struct" => true,
else => false,
};
if (!reflectable) {
if (self.diagnostics) |d| d.addFmt(.err, c.args[0].span, "type_info: '{s}' is not an enum — only enum/tagged-union reflection is supported today", .{self.formatTypeName(t)});
if (self.diagnostics) |d| d.addFmt(.err, c.args[0].span, "type_info: '{s}' is not reflectable — only enum / tagged-union / struct types reflect today", .{self.formatTypeName(t)});
return Ref.none;
}
const type_ref = self.builder.constType(t);