// A comptime-constructed type with NO members is VALID for every kind: // - an empty struct `struct {}` and empty tuple `()` are zero-size aggregates // you can instantiate (`.{}`), // - an empty enum and an empty tagged_union are valid uninhabited / zero-member // types — legitimate to NAME and reference even though they have no // constructible value (no variant to construct). // // This mirrors normal sx, where `struct {}` and `enum {}` already codegen fine; // the metatype `define`/`declare` path now agrees (the old blanket // "a type with no members is never valid" rejection is gone). // // The ONLY thing still rejected on this path is a bare `declare("X")` that is // never completed by a matching `define` — an INCOMPLETE forward slot that would // panic codegen. That case is exercised by examples/1179. #import "modules/std.sx"; #import "modules/std/meta.sx"; // Explicitly-defined empty types of every kind. EmptyStruct :: define(declare("EmptyStruct"), .struct(.{ fields = .[] })); EmptyTuple :: define(declare("EmptyTuple"), .tuple(.{ elements = .[] })); EmptyEnum :: define(declare("EmptyEnum"), .enum(.{ variants = .[] })); // An empty tagged_union (kind 3): no variants, but a valid named type. (The // `define` DSL maps an all-void variant set to a payloadless enum, so reach for // the register_type primitive directly to mint a 0-variant tagged_union.) EmptyUnion :: register_type(declare("EmptyUnion"), 3, .[]); main :: () -> i32 { // Instantiate the constructible ones. s : EmptyStruct = .{}; t : EmptyTuple = .{}; _ = s; _ = t; // EmptyEnum / EmptyUnion are uninhabited — valid as types, no value to make. print("empty struct/tuple/enum/tagged_union are all valid\n"); return 0; }