From dcdf1dd3180ce051dc62b743f8be2ff1a7b5424b Mon Sep 17 00:00:00 2001 From: agra Date: Wed, 17 Jun 2026 06:42:02 +0300 Subject: [PATCH] test(metatype): lock by-value self-ref rejection for constructed enums (1182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- ...tics-metatype-infinite-size-constructed.sx | 27 +++++++++++++++++++ ...cs-metatype-infinite-size-constructed.exit | 1 + ...-metatype-infinite-size-constructed.stderr | 1 + ...-metatype-infinite-size-constructed.stdout | 1 + 4 files changed, 30 insertions(+) create mode 100644 examples/1182-diagnostics-metatype-infinite-size-constructed.sx create mode 100644 examples/expected/1182-diagnostics-metatype-infinite-size-constructed.exit create mode 100644 examples/expected/1182-diagnostics-metatype-infinite-size-constructed.stderr create mode 100644 examples/expected/1182-diagnostics-metatype-infinite-size-constructed.stdout diff --git a/examples/1182-diagnostics-metatype-infinite-size-constructed.sx b/examples/1182-diagnostics-metatype-infinite-size-constructed.sx new file mode 100644 index 00000000..9c72f635 --- /dev/null +++ b/examples/1182-diagnostics-metatype-infinite-size-constructed.sx @@ -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; +} diff --git a/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.exit b/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.exit new file mode 100644 index 00000000..d00491fd --- /dev/null +++ b/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.exit @@ -0,0 +1 @@ +1 diff --git a/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.stderr b/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.stderr new file mode 100644 index 00000000..1567e2bf --- /dev/null +++ b/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.stderr @@ -0,0 +1 @@ +error: type 'L' is infinitely sized (it contains itself by value); use a pointer ('*L') to break the cycle diff --git a/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.stdout b/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.stdout new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/examples/expected/1182-diagnostics-metatype-infinite-size-constructed.stdout @@ -0,0 +1 @@ +