w6c+w6c_ww: >32B tagged INDEX/DOT reads go mem-based — box address in AX (#37)
A tagged box wider than the AX/DX/CX/R8 cursor (size > TUPLE_GPCAP*8)
read via N_INDEX or N_DOT now leaves its ADDRESS in AX — joining the
sret-call mem-based class the #38b gates already speak — and every
cursor consumer branches on one shared predicate (cg_tagged_memread /
taggedmemread) before reading AX as the tag. <=32B keeps the cursor
byte-for-byte (32B-at-cap asm proven identical to base on both the
t.N and INDEX routes).
Emitters: N_INDEX ident+fallback arms, N_DOT tuple-element (flips the
#22b loud bound), N_DOT struct-field + ptr-chained-field (were silent
clamps at 32B); wwstage twins gate cgloadtaggedfield at the helper
choke-point. Consumers: match spill x2 and the widen-store subset +
nested arms (the let/assign/return-widen/arg-widen/vararg choke-point)
copy the box from memory, then share the existing zero-pad + tag-remap
tail; `is` loads the tag through the address; `as` spills mem-based.
Rule-7 loud bounds replace silent cursor garbage for the non-mem-based
>32B kinds, `?`/`!`, and the 33-48B in-reg tagged arg push (mem-based
push stays the #35 family); the exact-type >32B return passthrough
from INDEX/DOT flips from its #38b loud into the widener route. The
pre-existing >48B memarg stack blit (cgplaceaddr) never used the
cursor and is pinned unchanged.
Reviewer-37 amendment: the non-mem-based >32B loud was ONE-SIDED on
two wwstage routes — cgwidentaggedstorebp had no fall-through guard
at all (`let w = *p` on a 56B box: cstage loud, wwstage silent word0
truncation), and cgmatch's guard keyed on matchscrutt-resolved
spillsz, which defaults under cap for kinds matchscrutt can't resolve
(N_UN deref et al), so `match (*p)` slipped it the same way. Both now
loud off the stamped src/scrut type_ (the kind-blind key cstage
already uses), restoring the rule-10 symmetry the body claims.
Emitters and consumers ship as ONE commit: they share the memread
contract, and splitting would open a transient window where a wired
emitter hands an address to an unwired consumer (silent garbage) —
the #61-precedent route-sharing fuse. The CX-global-tuple-base LEAQ
arm is TRIPWIRE wiring: a >32B tagged global-tuple element is
unreachable today (module-level tuple inits are int/str-literal-only;
tagged elements loud at the DATA emit), and the LEAQ keeps the same
base_reg generality as the cursor walk it replaces (ken note, task
record).
This was the last 5b compiler gate: `match insts[pc]` on the regex
inst union (inst_lit|inst_repeat, 56B) was silent-wrong gate-blind
byte-id on both stages (payload words 3+ dropped past the R8 clamp).
test 941 grows 165->200 checks: the #22b BUILDERR pin flips to a
runtime row, plus the 56B driver match, str+nested-tagged payload,
let/is/assign, indexed return, widening (identity and reversed-order
remap), 56B memarg, ken's X1 composition row, 32B-at-cap INDEX
boundary, the ptr-chained p.f match (BX-arm) and (*p)[i] fallback-arm
rows, and the two deref loud-symmetry BUILDERR pins. At base f272068
the 11 bug rows fail (2 BUILDERR flips + 7 silent-wrong + 2 missing-
loud pins, both drivers); the anchors pass. Oracle: ken PASS at
bf21964b pre-amendment; re-bind on the amended tree pending (source
bytes changed: cgenutil.ww/cgenexpr.ww louds + combined.ww regen).
This commit is contained in:
@@ -540,14 +540,16 @@ static const struct row rows[] = {
|
||||
"};\n", 0,
|
||||
K_BUILDERR, "#22b: tagged element in an over-cap (sret) tuple "
|
||||
"return from a non-ident or widening source unwired" },
|
||||
/* #37-class bound this arc newly exposed: a >32B box (40B =
|
||||
* (void|4x-u64-struct)) became transportable through the sret
|
||||
* routes, but the t.N READ rides the 4-reg AX/DX/CX/R8 cursor —
|
||||
* unbounded, cstage emitted INVALID ASM (tuple_rseq[4] OOB → w6a
|
||||
* "unsupported MOVQ shape") while wwstage clamped k>=3 to R8 and
|
||||
* silently dropped payload word 3. Now loud both stages; the
|
||||
* mem-based box read is #37's fold. */
|
||||
{ "b22_reject_big_box_read",
|
||||
/* #37 FLIP (was the #22b loud bound; BUILDERR at master a72e815
|
||||
* with "tagged tuple element read exceeds the AX/DX/CX/R8 box
|
||||
* cursor"): a >32B box t.N READ now leaves the box ADDRESS in AX
|
||||
* (cg_tagged_memread, the sret-receive convention) and every
|
||||
* cursor consumer copies from memory. The pre-#22b history: cstage
|
||||
* emitted INVALID ASM (tuple_rseq[4] OOB), wwstage clamped k>=3 to
|
||||
* R8 and silently dropped payload word 3. Readback covers the
|
||||
* is-test (N_TYPETEST mem tag load) AND the full payload through a
|
||||
* direct match on t.N (match-spill mem copy). */
|
||||
{ "c37_big_box_t0_read",
|
||||
"package main;\n"
|
||||
"type four = struct { a: u64, b: u64, c: u64, d: u64, };\n"
|
||||
"fn g() (void | four) = {\n"
|
||||
@@ -560,11 +562,383 @@ static const struct row rows[] = {
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let t = pr();\n"
|
||||
" if (!(t.0 is four)) { return 1; };\n"
|
||||
" if (t.1 != 7) { return 1; };\n"
|
||||
" if (!(t.0 is four)) { return 2; };\n"
|
||||
" match (t.0) {\n"
|
||||
" case let f: four => {\n"
|
||||
" if (f.a != 1) { return 3; };\n"
|
||||
" if (f.b != 2) { return 4; };\n"
|
||||
" if (f.c != 3) { return 5; };\n"
|
||||
" if (f.d != 4) { return 6; };\n"
|
||||
" };\n"
|
||||
" case void => { return 7; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37 THE 5b DRIVER SHAPE: `match insts[pc]` where inst =
|
||||
* (inst_lit | inst_repeat) = 56B (8 tag + 48 payload: 2x size +
|
||||
* 2x 16B nested tagged). SILENT-WRONG at master a72e815 (gate-
|
||||
* blind, byte-id both stages): the N_INDEX cursor load clamped at
|
||||
* R8, dropping payload words 3+ — min's payload and max's whole
|
||||
* box read stack garbage. Matches BOTH variants, reads every
|
||||
* nested-tagged field back. */
|
||||
{ "c37_idx_match_56",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type inst = (inst_lit | inst_repeat);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let insts: []inst = [];\n"
|
||||
" let r = inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(22: size)};\n"
|
||||
" append(insts, r);\n"
|
||||
" append(insts, ('A': inst_lit));\n"
|
||||
" let pc: size = 0;\n"
|
||||
" match (insts[pc]) {\n"
|
||||
" case let ir: inst_repeat => {\n"
|
||||
" if (ir.id != 7) { return 1; };\n"
|
||||
" if (ir.origin != 3) { return 2; };\n"
|
||||
" if (!(ir.min is size)) { return 3; };\n"
|
||||
" if (ir.min as size != 11) { return 4; };\n"
|
||||
" if (!(ir.max is size)) { return 5; };\n"
|
||||
" if (ir.max as size != 22) { return 6; };\n"
|
||||
" };\n"
|
||||
" case let l: inst_lit => { return 7; };\n"
|
||||
" };\n"
|
||||
" match (insts[1]) {\n"
|
||||
" case let l: inst_lit => {\n"
|
||||
" if (l != 'A') { return 8; };\n"
|
||||
" };\n"
|
||||
" case let ir: inst_repeat => { return 9; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37: str + nested-tagged payload variant — the big variant
|
||||
* carries a 24B str header AND a nested 16B box (64B union);
|
||||
* readback checks the str CONTENT survives the mem copy, not just
|
||||
* the tag. SILENT-WRONG at master (words 3+ dropped). */
|
||||
{ "c37_idx_match_str_nested",
|
||||
"package main;\n"
|
||||
"type lit2 = rune;\n"
|
||||
"type rep2 = struct {\n"
|
||||
" name: str,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type in2 = (lit2 | rep2);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: []in2 = [];\n"
|
||||
" let r = rep2{name=\"deadbeef\", min=(2: size), max=(5: size)};\n"
|
||||
" append(xs, r);\n"
|
||||
" match (xs[0]) {\n"
|
||||
" case let v: rep2 => {\n"
|
||||
" if (v.name.len != 8) { return 1; };\n"
|
||||
" if (v.name[0] != 'd') { return 2; };\n"
|
||||
" if (v.name[7] != 'f') { return 3; };\n"
|
||||
" if (!(v.min is size)) { return 4; };\n"
|
||||
" if (v.min as size != 2) { return 5; };\n"
|
||||
" if (v.max as size != 5) { return 6; };\n"
|
||||
" };\n"
|
||||
" case let l: lit2 => { return 7; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37: let-bind from a >32B indexed read (widener subset arm
|
||||
* mem-copy), then is-test directly on the indexed read (N_TYPETEST
|
||||
* mem tag load), then reassign (cgassign route). SILENT-WRONG at
|
||||
* master. */
|
||||
{ "c37_idx_let_is_assign",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type inst = (inst_lit | inst_repeat);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let insts: []inst = [];\n"
|
||||
" let r = inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(22: size)};\n"
|
||||
" append(insts, r);\n"
|
||||
" append(insts, ('A': inst_lit));\n"
|
||||
" if (!(insts[0] is inst_repeat)) { return 1; };\n"
|
||||
" if (insts[0] is inst_lit) { return 2; };\n"
|
||||
" let w = insts[0];\n"
|
||||
" match (w) {\n"
|
||||
" case let ir: inst_repeat => {\n"
|
||||
" if (ir.max as size != 22) { return 3; };\n"
|
||||
" };\n"
|
||||
" case let l: inst_lit => { return 4; };\n"
|
||||
" };\n"
|
||||
" w = insts[1];\n"
|
||||
" if (!(w is inst_lit)) { return 5; };\n"
|
||||
" w = insts[0];\n"
|
||||
" match (w) {\n"
|
||||
" case let ir: inst_repeat => {\n"
|
||||
" if (ir.min as size != 11) { return 6; };\n"
|
||||
" };\n"
|
||||
" case let l: inst_lit => { return 7; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37: exact-type >32B tagged RETURN from an indexed source — was
|
||||
* the "#38b: >32B tagged return from a cursor source" LOUD bound;
|
||||
* now routes through the widener's mem-read arm into the sret
|
||||
* dest. BUILDERR at master a72e815. */
|
||||
{ "c37_idx_return",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type inst = (inst_lit | inst_repeat);\n"
|
||||
"fn pick(insts: []inst, pc: size) inst = {\n"
|
||||
" return insts[pc];\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let insts: []inst = [];\n"
|
||||
" let r = inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(22: size)};\n"
|
||||
" append(insts, r);\n"
|
||||
" let w = pick(insts, 0);\n"
|
||||
" match (w) {\n"
|
||||
" case let ir: inst_repeat => {\n"
|
||||
" if (ir.id != 7) { return 1; };\n"
|
||||
" if (ir.min as size != 11) { return 2; };\n"
|
||||
" };\n"
|
||||
" case let l: inst_lit => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37: WIDENING let from a >32B indexed read — subset mem-copy +
|
||||
* zero-pad + (identity) tag remap; and the 56B (>48B MEMORY-class)
|
||||
* exact-type ARG from an indexed source (the pre-existing #38b
|
||||
* memarg stack-blit path, kept working alongside the new emitters:
|
||||
* cgplaceaddr never sees the cursor). */
|
||||
{ "c37_widen_and_memarg",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type inst = (inst_lit | inst_repeat);\n"
|
||||
"type wide = (inst_lit | inst_repeat | str);\n"
|
||||
"fn idof(i: inst) size = {\n"
|
||||
" match (i) {\n"
|
||||
" case let ir: inst_repeat => { return ir.id; };\n"
|
||||
" case let l: inst_lit => { return 999; };\n"
|
||||
" };\n"
|
||||
" return 998;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let insts: []inst = [];\n"
|
||||
" let r = inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(22: size)};\n"
|
||||
" append(insts, r);\n"
|
||||
" let w: wide = insts[0];\n"
|
||||
" match (w) {\n"
|
||||
" case let ir: inst_repeat => {\n"
|
||||
" if (ir.max as size != 22) { return 1; };\n"
|
||||
" };\n"
|
||||
" case let l: inst_lit => { return 2; };\n"
|
||||
" case let s2: str => { return 3; };\n"
|
||||
" };\n"
|
||||
" if (idof(insts[0]) != 7) { return 4; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37: NON-identity tag remap on a >32B mem-read widen — source
|
||||
* union declares its variants in REVERSED order vs dst, so the
|
||||
* widener's remap chain must fire (tag 0 -> 1) after the mem copy
|
||||
* + zero-pad. SILENT-WRONG at master a72e815. */
|
||||
{ "c37_widen_remap",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type rev = (inst_repeat | inst_lit);\n"
|
||||
"type wide = (inst_lit | inst_repeat | str);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let xs: []rev = [];\n"
|
||||
" let r = inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(22: size)};\n"
|
||||
" append(xs, r);\n"
|
||||
" let w: wide = xs[0];\n"
|
||||
" match (w) {\n"
|
||||
" case let ir: inst_repeat => {\n"
|
||||
" if (ir.id != 7) { return 1; };\n"
|
||||
" if (!(ir.max is size)) { return 2; };\n"
|
||||
" if (ir.max as size != 22) { return 3; };\n"
|
||||
" };\n"
|
||||
" case let l: inst_lit => { return 4; };\n"
|
||||
" case let s2: str => { return 5; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* ken X1 (/tmp/ken_22b_validation.md, impl-22b flag: ROW-WORTHY):
|
||||
* the #22a/#23/#22b/#37 composition — a #23-constructed box
|
||||
* ((void|st), st from an inline struct-lit with a NESTED TAGGED
|
||||
* FIELD, box exactly 32B = cursor AT cap) transported through the
|
||||
* #22b over-cap sret return, every field read back. */
|
||||
{ "c37_x1_compose",
|
||||
"package main;\n"
|
||||
"type st = struct { a: size, m: (void | size), };\n"
|
||||
"fn pr() ((void | st), size, size) = {\n"
|
||||
" let e: (void | st) = st{a=4: size, m=(2: size)};\n"
|
||||
" return (e, 5, 6);\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let t = pr();\n"
|
||||
" if (!(t.0 is st)) { return 1; };\n"
|
||||
" match (t.0) {\n"
|
||||
" case let v: st => {\n"
|
||||
" if (v.a != 4) { return 2; };\n"
|
||||
" if (!(v.m is size)) { return 3; };\n"
|
||||
" if (v.m as size != 2) { return 4; };\n"
|
||||
" };\n"
|
||||
" case void => { return 5; };\n"
|
||||
" };\n"
|
||||
" if (t.1 != 5) { return 6; };\n"
|
||||
" if (t.2 != 6) { return 7; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37 boundary neighbor: a 32B-EXACT (cursor AT cap) tagged
|
||||
* element INDEX read keeps the AX/DX/CX/R8 cursor — asm byte-
|
||||
* identical to master (probed: p6 asm unchanged vs a72e815).
|
||||
* Sister of b22_k5_box_at_cap (the t.N boundary). */
|
||||
{ "c37_idx_at_cap",
|
||||
"package main;\n"
|
||||
"type box = (void | str);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let bs: []box = [];\n"
|
||||
" let s: str = \"abcdefgh\";\n"
|
||||
" append(bs, s);\n"
|
||||
" match (bs[0]) {\n"
|
||||
" case let v: str => {\n"
|
||||
" if (v.len != 8) { return 1; };\n"
|
||||
" };\n"
|
||||
" case void => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37 ptr-chained route: match on p.f through a *struct base —
|
||||
* the cstage D_BX LEAQ arm / wwstage cgloadtaggedfield gate. The
|
||||
* only #37 emitter pair otherwise covered by probes alone (ken
|
||||
* M4); unlike the local-field shape (#42 cs!=ww divergence,
|
||||
* disclosed), the ptr-base spelling is byte-id. SILENT-WRONG at
|
||||
* master f272068 (exit 1, truncated payload). */
|
||||
{ "c37_ptr_field_match",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type inst = (inst_lit | inst_repeat);\n"
|
||||
"type holder = struct { pre: size, f: inst, };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let g = holder{pre=9: size, f=inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(55: size)}};\n"
|
||||
" let p = &g;\n"
|
||||
" if (!(p.f is inst_repeat)) { return 1; };\n"
|
||||
" match (p.f) {\n"
|
||||
" case let ir: inst_repeat => {\n"
|
||||
" if (ir.id != 7) { return 2; };\n"
|
||||
" if (ir.max as size != 55) { return 3; };\n"
|
||||
" };\n"
|
||||
" case let l: inst_lit => { return 4; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37 non-ident INDEX base: (*p)[i] rides the cgindex fallback
|
||||
* arm (AX already the element address — the emitter that LEAVES
|
||||
* AX rather than LEAQing). SILENT-WRONG at master f272068. */
|
||||
{ "c37_deref_idx_match",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type inst = (inst_lit | inst_repeat);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let insts: []inst = [];\n"
|
||||
" let r = inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(22: size)};\n"
|
||||
" append(insts, r);\n"
|
||||
" let p = &insts;\n"
|
||||
" match ((*p)[0]) {\n"
|
||||
" case let ir: inst_repeat => {\n"
|
||||
" if (ir.id != 7) { return 1; };\n"
|
||||
" if (ir.max as size != 22) { return 2; };\n"
|
||||
" };\n"
|
||||
" case let l: inst_lit => { return 3; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0, K_RUN, NULL },
|
||||
/* #37 loud-symmetry pin (reviewer-37): a >32B tagged WIDEN/let
|
||||
* source of a non-mem-based kind (deref) louds on BOTH stages.
|
||||
* Pre-amendment wwstage fell to the scalar word0 arm and ran
|
||||
* silent-wrong while cstage loud'ed (rule-10 break). */
|
||||
{ "c37_reject_deref_widen",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type inst = (inst_lit | inst_repeat);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let insts: []inst = [];\n"
|
||||
" let r = inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(22: size)};\n"
|
||||
" append(insts, r);\n"
|
||||
" let p = &insts[0];\n"
|
||||
" let w = *p;\n"
|
||||
" if (!(w is inst_repeat)) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0,
|
||||
K_BUILDERR, "tagged tuple element read exceeds the AX/DX/CX/R8 "
|
||||
"box cursor (mem-based read is the #37 family" },
|
||||
K_BUILDERR, "#37: >32B tagged source of a non-mem-based kind" },
|
||||
/* #37 loud-symmetry pin (reviewer-37): match on a >32B deref
|
||||
* scrutinee louds on BOTH stages. Pre-amendment wwstage's
|
||||
* matchscrutt returned nil for N_UN, spillsz defaulted under
|
||||
* cap, and the guard was blind — silent-wrong vs cstage loud. */
|
||||
{ "c37_reject_deref_match",
|
||||
"package main;\n"
|
||||
"type inst_lit = rune;\n"
|
||||
"type inst_repeat = struct {\n"
|
||||
" id: size,\n"
|
||||
" origin: size,\n"
|
||||
" min: (void | size),\n"
|
||||
" max: (void | size),\n"
|
||||
"};\n"
|
||||
"type inst = (inst_lit | inst_repeat);\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let insts: []inst = [];\n"
|
||||
" let r = inst_repeat{id=7: size, origin=3: size, min=(11: size), max=(22: size)};\n"
|
||||
" append(insts, r);\n"
|
||||
" let p = &insts[0];\n"
|
||||
" match (*p) {\n"
|
||||
" case let ir: inst_repeat => { return 1; };\n"
|
||||
" case let l: inst_lit => { return 2; };\n"
|
||||
" };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0,
|
||||
K_BUILDERR, "#37: >32B tagged match scrutinee from a non-mem-based source" },
|
||||
/* ...but the >32B TRANSPORT itself (sret send mem-to-mem + MLET
|
||||
* copy-out) is size-generic and correct — only the cursor read is
|
||||
* bounded. is-checks on the destructured local read the tag from
|
||||
|
||||
Reference in New Issue
Block a user