test(metatype): lock by-value self-ref rejection for constructed enums (1182)

Constructed-type companion to examples/1178 (source form): a declare/
define enum whose variant references itself BY VALUE is rejected by the
same checkInfiniteSize guard ('infinitely sized'). Pins the use-before-
define corner of the validation story — by-value self-reference is the
one self-ref shape that isn't legal; *L (pointer) is fine (see 0618).
No compiler change (locks existing behavior).
This commit is contained in:
agra
2026-06-17 06:42:02 +03:00
parent fe6799545a
commit dcdf1dd318
4 changed files with 30 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
// Diagnostic: a comptime-CONSTRUCTED enum (declare/define) that contains itself
// BY VALUE is infinitely sized and rejected loudly — the same `checkInfiniteSize`
// guard that covers source decls (examples/1178) also covers minted types. A
// pointer payload (`*L`) breaks the cycle and is the fix the message suggests
// (see examples/0618 for the working recursive `*List`).
//
// This is the constructed-type companion to 1178, and pins the "use-before-
// define by value" corner of the metatype validation story: referencing a
// declared slot by VALUE in its own definition is the one self-reference shape
// that isn't legal (a `*L` pointer needs no layout, so it is).
#import "modules/std.sx";
#import "modules/std/meta.sx";
make :: () -> Type {
h := declare("L");
return define(h, .enum(.{ variants = .[
EnumVariant.{ name = "cons", payload = L }, // by VALUE, not *L
EnumVariant.{ name = "nil", payload = void },
] }));
}
L :: make();
main :: () -> i32 {
x : L = .nil;
return 0;
}

View File

@@ -0,0 +1 @@
error: type 'L' is infinitely sized (it contains itself by value); use a pointer ('*L') to break the cycle