wcc/check: #26 recurse over-fill walk into nested tuple element (wwstage)

extracts the shared checktuplearrfits helper (also used by #25); wwstage-only checker reject-align, cstage already louds.
This commit is contained in:
2026-06-09 15:00:03 +09:00
parent 46e8354056
commit 89f3e58458
4 changed files with 144 additions and 56 deletions

View File

@@ -20,15 +20,17 @@
* asm; selfhost has no overlong tuple-elements, so 990-997 byte-id is
* untouched. Do NOT chase message parity.
*
* neg row | shape | gate
* -----------------+------------------------------------------------+--------
* tuple_arr_over | let t:([2]int,i32)=([1,2,3],5) | b. FAIL
* tuple_nested_arr | let t:([2][3]int,i32)=([[..],[..],[..]],5) | b. FAIL
* neg row | shape | gate
* -------------------+----------------------------------------------+--------
* tuple_arr_over | let t:([2]int,i32)=([1,2,3],5) | b. FAIL
* tuple_nested_arr | let t:([2][3]int,i32)=([[..],[..],[..]],5) | b. FAIL
* tuple_in_tuple | let t:([2]int,([2]int,i32))=([..],([1,2,3],.))| #26 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
* 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
*/
#include <stdio.h>
#include <stdlib.h>
@@ -72,6 +74,22 @@ static const struct row rows[] = {
"\treturn t.1;\n"
"};\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",
"package main;\n"
"export fn main() i32 = {\n"
"\tlet t: (i32, ([2]int, i32)) = (9, ([3, 4], 7));\n"
"\treturn t.0;\n"
"};\n",
9 },
};
/* An overlong array literal in a tuple element — both stages must FAIL the
@@ -91,6 +109,13 @@ static const char *neg[] = {
"([[1, 2, 3], [4, 5, 6], [7, 8, 9]], 5);\n"
"\treturn t.0[0][0]: i32;\n"
"};\n",
/* tuple_in_tuple (#26) — nested tuple element; inner [2]int over-
* filled by 3. The walk must RECURSE the nested tuple (let pos). */
"package main;\n"
"export fn main() i32 = {\n"
"\tlet t: ([2]int, ([2]int, i32)) = ([1, 2], ([3, 4, 5], 6));\n"
"\treturn t.0[0]: i32;\n"
"};\n",
};
static int