wcc/check: #24 reject composite-element tuple (array/struct/tuple), declared+inferred, both stages
A tuple whose element chases to TY_ARRAY/STRUCT/TUPLE (>8B) silently miscompiled both stages: t.0[i] read segfaulted and construction dropped the payload into the 8B slot. Reject the type at resolution (DISP-B); faithful inline layout deferred to #60. cstage resolve_type N_TTUPLE (declared) + N_TUPLE expr (inferred literal, was a cstage-only silent miscompile + cs!=ww asymmetry); wwstage tinfofornode covers both. test/wcc/832 + 941 migrated.
This commit is contained in:
@@ -20,6 +20,17 @@
|
||||
* asm; selfhost has no overlong tuple-elements, so 990-997 byte-id is
|
||||
* untouched. Do NOT chase message parity.
|
||||
*
|
||||
* #24 (DISP-B broad reject, rob spec .ai/rob-24-spec.md): a tuple whose
|
||||
* ELEMENT is a composite (array / struct / nested-tuple >8B) cannot ride the
|
||||
* 8B cursor slot (#60 layout) — it silently DROPS on construction and SEGVs
|
||||
* on the t.N[i] read. Both stages now REJECT such a type at N_TTUPLE
|
||||
* resolution (kind ∈ {TY_ARRAY, TY_STRUCT, TY_TUPLE} after TY_NAMED chase),
|
||||
* converting two silent miscompiles into one loud checker error. This FLIPS
|
||||
* the former tuple_arr_exact / tuple_nested_exact positive controls to the
|
||||
* neg table (their types are now outlawed) and adds slice/str/tagged-element
|
||||
* positive controls proving DISP-B does NOT over-reject the inline-header
|
||||
* kinds. Full inline support deferred to task #60 / DISP-A.
|
||||
*
|
||||
* neg row | shape | gate
|
||||
* -------------------+----------------------------------------------+--------
|
||||
* tuple_arr_over | let t:([2]int,i32)=([1,2,3],5) | b. FAIL
|
||||
@@ -27,12 +38,16 @@
|
||||
* tuple_in_tuple | let t:([2]int,([2]int,i32))=([..],([1,2,3],.))| #26 FAIL
|
||||
* tuple_return_over | fn()([2]int,i32){return([1,2,3],5)} | #25 FAIL
|
||||
* tuple_return_nested| fn()([2]int,([2]int,i32)){return(..,([..3],.))| #25 FAIL
|
||||
* tuple_arr_exact | let t:([2]int,i32)=([1,2],5) | #24 FAIL
|
||||
* tuple_nested_exact | let t:(i32,([2]int,i32))=(9,([3,4],7)) | #24 FAIL
|
||||
* tuple_struct_elem | type P=struct{x:int}; let t:(P,i32)=(P{x=1},5)| #24 FAIL
|
||||
*
|
||||
* pos row | shape | want
|
||||
* -------------------+----------------------------------------------+------
|
||||
* tuple_arr_exact | let t:([2]int,i32)=([1,2],5); t.1 | 5
|
||||
* tuple_scalar | let t:(i32,i32)=(1,2); t.1 | 2
|
||||
* tuple_nested_exact | let t:(i32,([2]int,i32))=(9,([3,4],7)); t.0 | 9
|
||||
* tuple_slice_elem | let t:([]u8,i32)=(a,5); t.1 | 5
|
||||
* tuple_str_elem | let t:(str,i32)=("hi",7); t.1 | 7
|
||||
* tuple_tagged_elem | let t:((void|size),i32)=(3,9); t.1 | 9
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -53,22 +68,7 @@ runwait(const char *cmd)
|
||||
struct row { const char *label; const char *src; int want; };
|
||||
|
||||
static const struct row rows[] = {
|
||||
/* exact-length array element in a tuple still ACCEPTS, builds + runs.
|
||||
* Readout is the scalar t.1 (=5), NOT t.0[1]: indexing an array
|
||||
* element THROUGH a tuple is a separate pre-existing cgen read bug
|
||||
* that segfaults on BOTH stages (w6c byte-identical, so not a #20
|
||||
* regression — filed). The point of this control is that the #20
|
||||
* over-fill walk does NOT over-reject the valid exact-length tuple-
|
||||
* with-array-element: the build must succeed and the program run. */
|
||||
{ "tuple_arr_exact",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
"\tlet t: ([2]int, i32) = ([1, 2], 5);\n"
|
||||
"\treturn t.1;\n"
|
||||
"};\n",
|
||||
5 },
|
||||
|
||||
/* a scalar-only tuple has no array element — the #20 walk no-ops. */
|
||||
/* a scalar-only tuple — all elements ride the 8B slot. */
|
||||
{ "tuple_scalar",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
@@ -77,19 +77,36 @@ static const struct row rows[] = {
|
||||
"};\n",
|
||||
2 },
|
||||
|
||||
/* #26 positive control — a VALID nested tuple with an exact-length
|
||||
* inner [2]int must NOT be over-rejected by the new recursion arm.
|
||||
* Readout is the top-level scalar t.0 (=9), NOT a leaf through the
|
||||
* inner tuple / array element (those hit pre-existing cgen read bugs
|
||||
* that miscompile on BOTH stages — filed, byte-id-blind, see the
|
||||
* tuple_arr_exact note). The point here is that checktuplearrfits
|
||||
* recurses the inner ([2]int,i32), runs the count check, and lets the
|
||||
* exact-length build proceed: build succeeds + program runs. */
|
||||
{ "tuple_nested_exact",
|
||||
/* #24 positive control — a SLICE element is DISP-B-allowed (its 24B
|
||||
* header rides the cursor). Must NOT be over-rejected. Readout is the
|
||||
* scalar t.1 (=5). */
|
||||
{ "tuple_slice_elem",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
"\tlet t: (i32, ([2]int, i32)) = (9, ([3, 4], 7));\n"
|
||||
"\treturn t.0;\n"
|
||||
"\tlet hb: [8]u8;\n"
|
||||
"\tlet a: []u8; a.ptr = &hb[0]; a.len = 3; a.cap = 8;\n"
|
||||
"\tlet t: ([]u8, i32) = (a, 5);\n"
|
||||
"\treturn t.1;\n"
|
||||
"};\n",
|
||||
5 },
|
||||
|
||||
/* #24 positive control — a STR element is DISP-B-allowed (24B header).
|
||||
* Readout is the scalar t.1 (=7). */
|
||||
{ "tuple_str_elem",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
"\tlet t: (str, i32) = (\"hi\", 7);\n"
|
||||
"\treturn t.1;\n"
|
||||
"};\n",
|
||||
7 },
|
||||
|
||||
/* #24 positive control — a TAGGED-UNION element is DISP-B-allowed (its
|
||||
* tag+payload box rides the slot). Readout is the scalar t.1 (=9). */
|
||||
{ "tuple_tagged_elem",
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
"\tlet t: ((void | size), i32) = (3, 9);\n"
|
||||
"\treturn t.1;\n"
|
||||
"};\n",
|
||||
9 },
|
||||
};
|
||||
@@ -137,6 +154,29 @@ static const char *neg[] = {
|
||||
"\tlet t = f();\n"
|
||||
"\treturn t.0[0]: i32;\n"
|
||||
"};\n",
|
||||
/* tuple_arr_exact (#24) — was a GREEN positive control; the DISP-B
|
||||
* broad reject now OUTLAWS an ARRAY tuple element (silent-drop on
|
||||
* construction + segv on t.0[i] read). MIGRATED to the neg table. */
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
"\tlet t: ([2]int, i32) = ([1, 2], 5);\n"
|
||||
"\treturn t.1;\n"
|
||||
"};\n",
|
||||
/* tuple_nested_exact (#24) — was a GREEN positive control; a NESTED
|
||||
* TUPLE element is now outlawed by DISP-B. MIGRATED to the neg table. */
|
||||
"package main;\n"
|
||||
"export fn main() i32 = {\n"
|
||||
"\tlet t: (i32, ([2]int, i32)) = (9, ([3, 4], 7));\n"
|
||||
"\treturn t.0;\n"
|
||||
"};\n",
|
||||
/* tuple_struct_elem (#24) — a STRUCT tuple element is now a checker
|
||||
* loud (was a cgen "unsupported field-read shape" loud). */
|
||||
"package main;\n"
|
||||
"type P = struct { x: int };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
"\tlet t: (P, i32) = (P { x = 1 }, 5);\n"
|
||||
"\treturn t.1;\n"
|
||||
"};\n",
|
||||
};
|
||||
|
||||
static int
|
||||
|
||||
Reference in New Issue
Block a user