wcc+w6c_ww: typed dot-read resolver — kill both silent N_DOT fallbacks (F4)

A typed depth-2+ field chain behind an index/deref spine
(threads[0].cap.end, (*p)[i].f.g) aborted the cgdot chain walker
(N_IDENT roots only) and fell into the module-qualified-leaf fallback
— a silent `MOVQ <leaf>(SB)` global read of a colliding symbol
(p6min10 exit 66) or a link error. Single-dot reads behind a deref-
index ((*ts)[i].pc, (*p)[i].slicefield) fell into the bottom catch-all
instead, which is offset- and header-blind: offset-0 scalars read
correctly by COINCIDENCE, nonzero offsets and slice headers were
silently wrong in BOTH stages (FA3, pA5). `&threads[0].cap` dropped
the address-of silently and SEGFAULTed at the deref (task #6,
reviewer-A route).

cgplaceaddr (C1) grows an N_IDENT root (local / let / DATA-backed
def) and the N_INDEX base gate relaxes to recursion, so indexed-ident
and deref-rooted spines resolve; enumerated arms still dispatch first,
keeping every pre-C1 shape's asm. case N_DOT routes any TYPED read no
arm matched through the resolver (scalar fldloadop, float X0, str/
slice 3-word header, [N]T address); the module-leaf fallback is gated
to UNTYPED chains, the catch-all to untyped-str pseudo-fields, and
the TK_AMP tail is resolver-or-loud. Leaf kinds without a register
convention (tagged, aggregate) and unaddressable shapes die LOUD
(rule 7). wwstage mirrors symmetrically; two of its arm gaps must not
take the resolver (its sequence differs from cstage's arms — cs!=ww):
ident-indexed alias reads loud-cite C3 (task #8) and non-local-rooted
ptr-chains loud-cite task #37. A third verdict divergence is comment-
documented at the wwstage aggregate gate: cstage's let-init consumes
`let c = (*ts)[i].cap` BEFORE its N_DOT tail (emitting NO copy — the
F5 bug), so that shape cs-builds/ww-louds until the F5 let-copy lands
(task #7); absent from the gate corpus.

806 identroot_dot graduates from BUILD_FAIL: the C2 ident root makes
append(h.xs, v) through *holder resolve via C1.5's place consumer
(run-verified, byte-id). p6min9/p6min10 read-halves are fixed but the
probes stay blocked on the #36 literal under-copy this commit
unmasked (struct-ident field rhs copies 8B; repro filed with the
task).

test/805: +7 rows (typed depth-2 behind ident-index incl the 777
global-collision pin, deref-index, width/float/[N]u8 matrix, FA3
slice-field + .cap-behind-spine, &-route with compound-through-
pointer, C1's reject_tail graduated to stores, neutrality pins) and
+4 reject rows pinning the new loud texts; the C1.25 raw-byte
readbacks graduate to typed depth-2 reads.
This commit is contained in:
2026-06-04 10:51:56 +09:00
parent b630a7cf20
commit 76994a8279
6 changed files with 1112 additions and 220 deletions

View File

@@ -24,6 +24,21 @@
* diagnostics — the reject rows pin the exact text on BOTH stages.
* Non-DOT lvalue tail residue is task #22.
*
* C2 (F4 + FA3-cstage, task #6): the READ side. cgplaceaddr grew an
* N_IDENT root and recursion-driven N_INDEX bases; case N_DOT routes
* every TYPED read no enumerated arm matched through the resolver, and
* BOTH silent fallbacks died: the module-leaf `MOVQ <leaf>(SB)` is
* gated to UNTYPED chains (pre-C2 it swallowed any unmatched dot chain
* — a silent global read of a colliding symbol), and the offset-blind
* cgexpr catch-all is gated to untyped-str pseudo-fields (pre-C2 a
* nonzero-offset field behind a deref-index spine read element word 0;
* offset-0 scalars worked by coincidence). TK_AMP's silent tail is the
* same resolver-or-loud (`&threads[0].cap` used to SEGFAULT on deref,
* reviewer-A route). The C1.25 raw-byte readbacks graduate to typed
* depth-2 reads below. wwstage cgdot/cgun mirror symmetrically; its
* name-keyed ident-indexed arm gap stays LOUD (C3/task #8 re-key), as
* does the ptr-chained global-root remainder (task #37).
*
* row | shape | want
* --------------------+----------------------------------------+------
* store_size_neighbor | (*ts)[1].pc = 9, elem 0 intact | 19
@@ -55,7 +70,22 @@
* reject_float | f64 field store | BUILD_FAIL
* reject_tagged | tagged-union field store | BUILD_FAIL
* reject_str_compound | (*ts)[i].name += — str/slice compound | BUILD_FAIL
* reject_tail | h.arr[1].pc (resolver-unwired N_DOT) | BUILD_FAIL
* arr_field_idx_store | h.arr[1].pc = / += (C1's reject_tail, | 58
* | graduated by the C2 resolver arms) |
* read_depth2_idx | ts[i].cap.start/.end/.content.len — | 59
* | typed depth-2 behind an IDENT index |
* read_depth2_deref | (*ts)[i].cap.start + offset-0 .pc | 60
* read_widths_spine | i8..u32/f64/f32/[3]u8 behind (*p)[i] | 61
* read_slicefield | let h = (*p)[i].xs (FA3/pA5) + .cap | 62
* amp_spine | &ts[1].cap / &(*p)[0].cap — deref, | 63
* | compound through the pointer |
* neutral_reads | ident-root chain, "abc".len, (*p).f — | 64
* | untouched-arm asm-neutrality pins |
* reject_read_tagged | (*ts)[i].tg read behind spine | BUILD_FAIL
* reject_read_callbase| mk()[0].pc read (unaddressable base) | BUILD_FAIL
* reject_assign_callbs| mk()[0].pc = (assign-tail text keeps | BUILD_FAIL
* | its carrier post arr_field_idx_store) |
* reject_addrof_callbs| &mk()[0].pc (TK_AMP loud tail) | BUILD_FAIL
*
* BUILD_FAIL rows also assert the diagnostic TEXT (stderr substring,
* both stages) — a build that fails for any other reason (parse error,
@@ -383,14 +413,10 @@ static const struct row rows[] = {
* through a FRESH per-use @placescr materialise + word-copy; the
* `...` setter pins the autofill zero loop; neighbour element +
* sibling field readbacks pin the stride and copy length. */
/* Readback is RAW bytes over ts.ptr (the 804 tagged_56b
* precedent): a depth-2 read behind an index (ts[1].cap.start)
* is the F4 walker gap (task #6) and link-fails today on the
* cgen.c:9038 global-leaf fallback — typed readbacks graduate
* with the C2 read-walker. Layout: t={pc@0,cap@8}, size 48;
* capture={content(str ptr@0,len@8,cap@16),start@24,end@32}.
* Elem1 base 48 → content.len byte 64, start 80, end 88;
* elem0 → 16/32/40. Stored values fit one byte. */
/* Readback was RAW bytes over ts.ptr until C2 — a depth-2 read
* behind an index (ts[1].cap.start) was the F4 walker gap (task
* #6) and link-failed on the cgen.c global-leaf fallback. C2
* graduation: typed depth-2 readbacks (the documented note). */
{ "agg_structlit_40b",
"package main;\n"
"type capture = struct { content: str, start: size, end: size };\n"
@@ -407,24 +433,23 @@ static const struct row rows[] = {
"\tappend(ts, t { pc = 7, cap = z });\n"
"\tappend(ts, t { pc = 8, cap = z });\n"
"\tsetcap(&ts, 1);\n"
"\tlet bp: *u8 = ts.ptr: *u8;\n"
"\tif (bp[64] != 3u8) { return 1; };\n"
"\tif (bp[80] != 2u8) { return 2; };\n"
"\tif (bp[88] != 4u8) { return 3; };\n"
"\tif (ts[1].cap.content.len != 3) { return 1; };\n"
"\tif (ts[1].cap.start != 2) { return 2; };\n"
"\tif (ts[1].cap.end != 4) { return 3; };\n"
"\tif (ts[1].pc != 8) { return 4; };\n"
"\tif (bp[16] != 0u8) { return 5; };\n"
"\tif (ts[0].cap.content.len != 0) { return 5; };\n"
"\tif (ts[0].pc != 7) { return 6; };\n"
"\tclearcap(&ts, 1);\n"
"\tif (bp[64] != 1u8) { return 7; };\n"
"\tif (bp[80] != 0u8) { return 8; };\n"
"\tif (bp[88] != 0u8) { return 9; };\n"
"\tif (ts[1].cap.content.len != 1) { return 7; };\n"
"\tif (ts[1].cap.start != 0) { return 8; };\n"
"\tif (ts[1].cap.end != 0) { return 9; };\n"
"\treturn 52;\n"
"};\n",
52, NULL },
/* Addressable aggregate sources via the #265/#268 dispatch:
* local ident (LEAQ slot) and deref (*pc). Raw-byte readback per
* the agg_structlit_40b layout note (F4 blocks typed depth-2). */
* local ident (LEAQ slot) and deref (*pc). Typed depth-2
* readbacks since C2 (were raw bytes over ts.ptr). */
{ "agg_from_ident_deref",
"package main;\n"
"type capture = struct { content: str, start: size, end: size };\n"
@@ -442,16 +467,15 @@ static const struct row rows[] = {
"\tappend(ts, t { pc = 8, cap = z });\n"
"\tlet a: capture = capture { content = \"ab\", start = 1, end = 3 };\n"
"\tcopycap(&ts, 1, a);\n"
"\tlet bp: *u8 = ts.ptr: *u8;\n"
"\tif (bp[64] != 2u8) { return 1; };\n"
"\tif (bp[80] != 1u8) { return 2; };\n"
"\tif (bp[88] != 3u8) { return 3; };\n"
"\tif (ts[1].cap.content.len != 2) { return 1; };\n"
"\tif (ts[1].cap.start != 1) { return 2; };\n"
"\tif (ts[1].cap.end != 3) { return 3; };\n"
"\tlet b: capture = capture { content = \"wxyz\", start = 5, end = 9 };\n"
"\tderefcap(&ts, 0, &b);\n"
"\tif (bp[16] != 4u8) { return 4; };\n"
"\tif (bp[32] != 5u8) { return 5; };\n"
"\tif (bp[40] != 9u8) { return 6; };\n"
"\tif (bp[80] != 1u8) { return 7; };\n"
"\tif (ts[0].cap.content.len != 4) { return 4; };\n"
"\tif (ts[0].cap.start != 5) { return 5; };\n"
"\tif (ts[0].cap.end != 9) { return 6; };\n"
"\tif (ts[1].cap.start != 1) { return 7; };\n"
"\treturn 53;\n"
"};\n",
53, NULL },
@@ -524,13 +548,12 @@ static const struct row rows[] = {
"\tappend(ts, t { pc = 7, cap = z });\n"
"\tappend(ts, t { pc = 8, cap = z });\n"
"\tsettwo(&ts);\n"
"\tlet bp: *u8 = ts.ptr: *u8;\n"
"\tif (bp[16] != 2u8) { return 1; };\n"
"\tif (bp[32] != 1u8) { return 2; };\n"
"\tif (bp[40] != 2u8) { return 3; };\n"
"\tif (bp[64] != 3u8) { return 4; };\n"
"\tif (bp[80] != 3u8) { return 5; };\n"
"\tif (bp[88] != 4u8) { return 6; };\n"
"\tif (ts[0].cap.content.len != 2) { return 1; };\n"
"\tif (ts[0].cap.start != 1) { return 2; };\n"
"\tif (ts[0].cap.end != 2) { return 3; };\n"
"\tif (ts[1].cap.content.len != 3) { return 4; };\n"
"\tif (ts[1].cap.start != 3) { return 5; };\n"
"\tif (ts[1].cap.end != 4) { return 6; };\n"
"\treturn 56;\n"
"};\n",
56, NULL },
@@ -655,19 +678,239 @@ static const struct row rows[] = {
BUILD_FAIL,
"assign-resolver: compound on str/slice field not wired (rule-7)" },
/* An N_DOT lvalue the C1 resolver does not wire (index base is a
* dot chain, not a deref) — pre-C1 this was a SILENT no-op store;
* the loud dispatch tail is the close-by-construction net. */
{ "reject_tail",
/* C1's reject_tail (index base is a dot chain), graduated by the
* C2 resolver arms (N_IDENT root + recursive N_INDEX bases) —
* store, compound, readback, and neighbour-intact pins. */
{ "arr_field_idx_store",
"package main;\n"
"type t = struct { pc: size, matched: bool };\n"
"type holder = struct { arr: [3]t, n: i64 };\n"
"export fn main() i32 = {\n"
"\tlet h: holder = holder { n = 0, ... };\n"
"\th.arr[1].pc = 5;\n"
"\th.arr[1].pc += 2;\n"
"\tif (h.arr[1].pc != 7) { return 1; };\n"
"\tif (h.arr[0].pc != 0) { return 2; };\n"
"\tif (h.arr[2].pc != 0) { return 3; };\n"
"\treturn 58;\n"
"};\n",
58, NULL },
/* C2 (F4): typed depth-2 reads behind an IDENT-indexed root —
* the p6min9/p6min10 read shape (nonzero offsets, both elements,
* pseudo .len behind the spine, and the global-collision check:
* a module global named `end` must NOT be read). Elements are
* built with NESTED literals, not `cap = rc1` ident rhs — the
* probes' own construction shape is the #36 under-copy (struct-
* ident field rhs copies 8B), which keeps p6min9/p6min10
* themselves blocked on #36 with their read-half fixed here. */
{ "read_depth2_idx",
"package main;\n"
"type capture = struct { content: str, start: size, end: size };\n"
"type t = struct { pc: size, cap: capture };\n"
"let end: size = 777;\n"
"export fn main() i32 = {\n"
"\tlet ts: []t = [];\n"
"\tappend(ts, t { pc = 5, cap = capture { content = \"abc\", start = 11, end = 13 } });\n"
"\tappend(ts, t { pc = 6, cap = capture { content = \"wy\", start = 21, end = 23 } });\n"
"\tif (ts[0].cap.end == 777) { return 66; };\n"
"\tif (ts[0].cap.end != 13) { return 1; };\n"
"\tif (ts[0].cap.start != 11) { return 2; };\n"
"\tif (ts[1].cap.end != 23) { return 3; };\n"
"\tif (ts[1].cap.content.len != 2) { return 4; };\n"
"\tif (ts[1].pc != 6) { return 5; };\n"
"\treturn 59;\n"
"};\n",
59, NULL },
/* C2 (F4): the same chain behind a DEREF-rooted index — plus the
* offset-0 scalar (.pc) that pre-C2 cstage read correctly only by
* COINCIDENCE through the offset-blind catch-all (ken's FA3
* correction); now it routes through the resolver in both
* stages. */
{ "read_depth2_deref",
"package main;\n"
"type capture = struct { content: str, start: size, end: size };\n"
"type t = struct { pc: size, cap: capture };\n"
"fn rd(ts: *[]t) i32 = {\n"
"\tif ((*ts)[0].pc != 5) { return 1; };\n"
"\tif ((*ts)[0].cap.start != 11) { return 2; };\n"
"\tif ((*ts)[0].cap.end != 13) { return 3; };\n"
"\tif ((*ts)[1].cap.end != 23) { return 4; };\n"
"\treturn 0;\n"
"};\n"
"export fn main() i32 = {\n"
"\tlet ts: []t = [];\n"
"\tappend(ts, t { pc = 5, cap = capture { content = \"abc\", start = 11, end = 13 } });\n"
"\tappend(ts, t { pc = 6, cap = capture { content = \"wy\", start = 21, end = 23 } });\n"
"\tlet rc: i32 = rd(&ts);\n"
"\tif (rc != 0) { return rc; };\n"
"\treturn 60;\n"
"};\n",
60, NULL },
/* C2 (F4): leaf-kind matrix behind the deref-index spine — narrow
* signed/unsigned (fldloadop sign/zero extension), f64/f32 via
* X0, and an `[N]u8` field leaf (address semantics, outer index
* applies). */
{ "read_widths_spine",
"package main;\n"
"type inner = struct { b: i8, ub: u8, w: i16, uw: u16, d: i32, ud: u32, f: f64, g: f32, arr: [3]u8 };\n"
"type box = struct { pad: size, it: inner };\n"
"export fn main() i32 = {\n"
"\tlet bs: []box = [];\n"
"\tappend(bs, box { pad = 1, it = inner { b = -5i8, ub = 200u8, w = -300i16, uw = 60000u16, d = -70000, ud = 4000000000u32, f = 1.5, g = 2.5f32, arr = [7u8, 8u8, 9u8] } });\n"
"\tlet p: *[]box = &bs;\n"
"\tif ((*p)[0].it.b != -5i8) { return 1; };\n"
"\tif ((*p)[0].it.ub != 200u8) { return 2; };\n"
"\tif ((*p)[0].it.w != -300i16) { return 3; };\n"
"\tif ((*p)[0].it.uw != 60000u16) { return 4; };\n"
"\tif ((*p)[0].it.d != -70000) { return 5; };\n"
"\tif ((*p)[0].it.ud != 4000000000u32) { return 6; };\n"
"\tif ((*p)[0].it.f != 1.5) { return 7; };\n"
"\tif ((*p)[0].it.g != 2.5f32) { return 8; };\n"
"\tif ((*p)[0].it.arr[1] != 8u8) { return 9; };\n"
"\treturn 61;\n"
"};\n",
61, NULL },
/* FA3/pA5 graduated: 24B slice-header field read behind a deref-
* index spine — pre-C2 cstage took the offset-blind catch-all
* (one wrong-offset MOVQ + stale BX/CX as the header), wwstage
* silently emitted NOTHING. Plus the .cap pseudo behind the same
* spine (recurses through the resolver). */
{ "read_slicefield",
"package main;\n"
"type box = struct { pc: size, xs: []size };\n"
"fn grab(p: *[]box, i: size) i32 = {\n"
"\tlet h: []size = (*p)[i].xs;\n"
"\tif (len(h) != 2) { return 1; };\n"
"\tif (h[0] != (7: size)) { return 2; };\n"
"\tif (h[1] != (8: size)) { return 3; };\n"
"\tif ((*p)[i].xs.cap < 2) { return 4; };\n"
"\treturn 0;\n"
"};\n"
"export fn main() i32 = {\n"
"\tlet src: []size = [];\n"
"\tappend(src, (7: size));\n"
"\tappend(src, (8: size));\n"
"\tlet bs: []box = [];\n"
"\tappend(bs, box { pc = 1, xs = src });\n"
"\tlet rc: i32 = grab(&bs, 0);\n"
"\tif (rc != 0) { return rc; };\n"
"\treturn 62;\n"
"};\n",
62, NULL },
/* Reviewer-A route: address-of a field through an indexed /
* deref-indexed spine, then deref + compound through the pointer.
* Pre-C2 BOTH stages silently dropped the & (stale AX as the
* address — gate-blind SEGFAULT). */
{ "amp_spine",
"package main;\n"
"type capture = struct { content: str, start: size, end: size };\n"
"type t = struct { pc: size, cap: capture };\n"
"fn bump(cp: *capture) void = { cp.end += 100; };\n"
"export fn main() i32 = {\n"
"\tlet ts: []t = [];\n"
"\tappend(ts, t { pc = 5, cap = capture { content = \"abc\", start = 11, end = 13 } });\n"
"\tappend(ts, t { pc = 6, cap = capture { content = \"wy\", start = 21, end = 23 } });\n"
"\tlet cp: *capture = &ts[1].cap;\n"
"\tif (cp.start != 21) { return 1; };\n"
"\tbump(cp);\n"
"\tif (ts[1].cap.end != 123) { return 2; };\n"
"\tlet pp: *[]t = &ts;\n"
"\tlet dp: *capture = &(*pp)[0].cap;\n"
"\tif (dp.end != 13) { return 3; };\n"
"\treturn 63;\n"
"};\n",
63, NULL },
/* Asm-neutrality pins for the arms the C2 gates must NOT disturb:
* ident-rooted value chain (chain walker), `(*p).f` retarget,
* untyped-str literal pseudo-fields (the gated catch-all's only
* legitimate tenant). A tuple-positional pin is blocked by the
* pre-existing #33 wwstage tuple-let word-2 drop (filed). */
{ "neutral_reads",
"package main;\n"
"type capture = struct { content: str, start: size, end: size };\n"
"type t = struct { pc: size, cap: capture };\n"
"fn pcof(p: *t) size = { return (*p).pc; };\n"
"export fn main() i32 = {\n"
"\tlet x: t = t { pc = 9, cap = capture { content = \"hi\", start = 1, end = 2 } };\n"
"\tif (x.cap.start != 1) { return 1; };\n"
"\tif (x.cap.content.len != 2) { return 2; };\n"
"\tif (pcof(&x) != 9) { return 3; };\n"
"\tif (\"abc\".len != 3) { return 4; };\n"
"\treturn 64;\n"
"};\n",
64, NULL },
/* Tagged leaf behind a spine: no canonical register convention
* is emitted by the read-resolver yet — must die LOUD, not load
* 8 of 16+ bytes (rule 7). */
{ "reject_read_tagged",
"package main;\n"
"type v = (i64 | bool);\n"
"type t = struct { pc: size, tg: v };\n"
"fn rd(ts: *[]t, i: size) i64 = {\n"
"\tlet x: v = (*ts)[i].tg;\n"
"\treturn 1;\n"
"};\n"
"export fn main() i32 = {\n"
"\tlet ts: []t = [];\n"
"\treturn rd(&ts, 0): i32;\n"
"};\n",
BUILD_FAIL, "read-resolver: tagged field read not wired (rule-7)" },
/* A call-result index base has no storage address — the resolver
* must refuse and the read tail must be LOUD (pre-C2: cstage
* emitted an offset-blind garbage read, wwstage nothing). */
{ "reject_read_callbase",
"package main;\n"
"type t = struct { pc: size, matched: bool };\n"
"fn mk() []t = {\n"
"\tlet ts: []t = [];\n"
"\tappend(ts, t { pc = 3, matched = true });\n"
"\treturn ts;\n"
"};\n"
"export fn main() i32 = {\n"
"\tif (mk()[0].pc != 3) { return 1; };\n"
"\treturn 0;\n"
"};\n",
BUILD_FAIL, "unsupported field-read shape" },
/* The assign-tail diagnostic keeps a carrier now that C1's
* reject_tail shape (h.arr[1].pc) graduated: a call-base lvalue
* is unaddressable. */
{ "reject_assign_callbase",
"package main;\n"
"type t = struct { pc: size, matched: bool };\n"
"fn mk() []t = {\n"
"\tlet ts: []t = [];\n"
"\tappend(ts, t { pc = 3, matched = true });\n"
"\treturn ts;\n"
"};\n"
"export fn main() i32 = {\n"
"\tmk()[0].pc = 2;\n"
"\treturn 0;\n"
"};\n",
BUILD_FAIL, "unsupported assign target shape" },
/* TK_AMP loud tail (the C2 replacement for the silent drop). */
{ "reject_addrof_callbase",
"package main;\n"
"type t = struct { pc: size, matched: bool };\n"
"fn mk() []t = {\n"
"\tlet ts: []t = [];\n"
"\tappend(ts, t { pc = 3, matched = true });\n"
"\treturn ts;\n"
"};\n"
"export fn main() i32 = {\n"
"\tlet p: *size = &mk()[0].pc;\n"
"\treturn (*p): i32;\n"
"};\n",
BUILD_FAIL, "unsupported address-of shape" },
};
/* errlog_has — the build-failure stderr must carry the row's expected

View File

@@ -42,8 +42,8 @@
* | — nested indirect append inside the |
* | outer's value expr; pins the per-SITE |
* | @apphdrscr slot (a shared slot clobbers)|
* reject_identroot_dot | h.xs via *holder param (resolver ident | BUILD_FAIL
* | root unwired — was silent corruption) |
* identroot_dot | h.xs via *holder param — C1.5's reject, | 73
* | graduated by C2's resolver ident root |
* reject_spread_src | non-ident spread SOURCE through a deref | BUILD_FAIL
* | target (the #35 designed boundary) |
*
@@ -372,20 +372,28 @@ static const struct row rows[] = {
"};\n",
33, NULL },
/* Ident-rooted dot target (h.xs through *holder): the resolver
* does not wire ident roots (they belong to the enumerated arms;
* none exists for append yet) — pre-fix this shape silently
* corrupted the frame in cstage; now it must die LOUD. */
{ "reject_identroot_dot",
/* Ident-rooted dot target (h.xs through *holder): C1.5's loud
* boundary (the resolver had no ident root then; pre-FA1 this
* shape silently corrupted the frame in cstage), graduated by
* C2's cgplaceaddr N_IDENT root — the *holder base derefs once
* inside the N_DOT hop and the header place lands on &h.xs.
* Readbacks use the .len pseudo, not len(): len() of a non-tuple
* N_DOT is the pre-existing F2 enumeration gap (task #10). */
{ "identroot_dot",
"package main;\n"
"type holder = struct { tag: i64, xs: []i64 };\n"
"fn addfield(h: *holder, v: i64) void = { append(h.xs, v); };\n"
"export fn main() i32 = {\n"
"\tlet hl: holder = holder { tag = 2, xs = [] };\n"
"\taddfield(&hl, 9);\n"
"\treturn 0;\n"
"\taddfield(&hl, 11);\n"
"\tif (hl.xs[0] != 9) { return 1; };\n"
"\tif (hl.xs[1] != 11) { return 2; };\n"
"\tif (hl.xs.len != 2) { return 3; };\n"
"\tif (hl.tag != 2) { return 4; };\n"
"\treturn 73;\n"
"};\n",
BUILD_FAIL, "#15: append() target place unsupported (rule-7)" },
73, NULL },
/* The FA4 designed boundary (task #35, old #37): a spread SOURCE that is
* not an ident local must stay loud even now that the deref