comptime VM: Phase 3 — register_type write side + payloadless-enum fixes
The mutating compiler-API, minting types LAZILY at lowering time (single pass,
the existing runComptimeTypeFunc path — so the write side is legacy-only; the
VM isn't wired at lowering time, and the read-side readers stay dual-path):
declare_type(name) -> Type forward nominal handle (≈ declare)
pointer_to(t) -> Type build *T references
register_type(handle, kind, members) ONE kind-branching fill (≈ unified define)
register_type branches on kind IN THE COMPILER (subsuming define's per-kind
dispatch); codes match type_kind: 1 struct, 2 actual .@"enum", 3 tagged_union,
4 tuple. Members are {name: string, ty: Type}. A non-generic `-> Type` builder is
now flagged is_comptime (decl.zig) so its dead body permits the welded calls.
Graph support: forward declare_type handles + pointer_to express a mutually-
recursive A<->B graph (*A, *B, B-by-value) before bodies are filled. register_type
is idempotent — re-filling a nominal slot (a minting module reached via two import
edges) re-mints identically rather than erroring (nominalIdent reads identity from
any nominal kind).
Fixes (issue 0142):
- A fully payloadless comptime-minted enum was minted as an all-void tagged_union,
whose IR size disagrees with its LLVM size -> verifySizes panic. Now mints a real
.@"enum" (register_type kind 2 AND the metatype defineEnum).
- Bare `EnumType.variant` qualified construction of a payloadless variant wasn't
supported (failed for hand-written enums too — the type name lowered to a Type
value). Added in lowerFieldAccess via isPayloadlessVariant; payload-carrying
variants keep their call form.
Examples: 0631 (graph + actual enum + reflection), 0632 (make_enum all-void),
0633/0634/0635 (namespaced / bare / multi-edge import of a minted type), 0187
(qualified variant construction). Unit tests added.
Parity 697/697 (gate OFF and -Dcomptime-flat).
This commit is contained in:
@@ -2197,10 +2197,37 @@ pub const Interpreter = struct {
|
||||
}
|
||||
|
||||
// Complete the declared slot IN PLACE: it already has its name + nominal
|
||||
// id (from `declare`); fill the body. Name/id unchanged → the intern key
|
||||
// is stable, so `updatePreservingKey`.
|
||||
// id (from `declare`); fill the body.
|
||||
const cur = tbl.get(handle);
|
||||
if (cur != .tagged_union) return bailDetail("comptime define(): handle is not a declare()'d enum slot");
|
||||
|
||||
// A FULLY payloadless variant set (every payload `void`) is an actual
|
||||
// enum — mint a `.@"enum"`, exactly like a hand-written `enum { a; b; }`.
|
||||
// Minting it as an all-void `tagged_union` instead gives a type whose IR
|
||||
// size disagrees with its LLVM size (a tag, but no payload storage), which
|
||||
// trips `verifySizes` at codegen. A kind change re-keys the slot, so
|
||||
// `replaceKeyedInfo` (not `updatePreservingKey`, which asserts the kind is
|
||||
// stable — true only for the tagged_union path below).
|
||||
var all_void = true;
|
||||
for (fields.items) |f| {
|
||||
if (f.ty != .void) {
|
||||
all_void = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all_void) {
|
||||
var variants = std.ArrayList(types.StringId).empty;
|
||||
for (fields.items) |f| variants.append(self.alloc, f.name) catch return error.CannotEvalComptime;
|
||||
const en: types.TypeInfo = .{ .@"enum" = .{
|
||||
.name = cur.tagged_union.name,
|
||||
.variants = variants.items,
|
||||
.nominal_id = cur.tagged_union.nominal_id,
|
||||
} };
|
||||
tbl.replaceKeyedInfo(handle, en);
|
||||
return .{ .value = .{ .type_tag = handle } };
|
||||
}
|
||||
|
||||
// Payload-carrying enum → tagged_union. Name/id unchanged → stable key.
|
||||
const full: types.TypeInfo = .{ .tagged_union = .{
|
||||
.name = cur.tagged_union.name,
|
||||
.fields = fields.items,
|
||||
@@ -2305,7 +2332,7 @@ pub const Interpreter = struct {
|
||||
/// A `[]EnumVariant` slice evaluates to a `{ data, len }` aggregate (`len` an
|
||||
/// int); a `[N]EnumVariant` array literal evaluates to the element aggregate
|
||||
/// directly. Returns null for any other shape (the caller bails loudly).
|
||||
fn decodeVariantElements(result: Value) ?[]const Value {
|
||||
pub fn decodeVariantElements(result: Value) ?[]const Value {
|
||||
const fields = switch (result) {
|
||||
.aggregate => |f| f,
|
||||
else => return null,
|
||||
|
||||
Reference in New Issue
Block a user