Files
ww/test/lang/deref_slice_store_test.ww
Hojun-Cho 83f5956df2 test: banner purge + WHY-only comment sweep (rule 8)
Every section banner dies (103 -> 0) across test/lang, the observer
suites, the C carriers, and the five comment-heavy corpus fixtures;
banner provenance (#N cites, carrier numbers, repair-cluster labels)
folded into headers or adjacent WHY comments. Narration deleted; row
provenance, ref cites, divergence pins, and layout contracts kept
(fwd-ref decl-order guards and bootstrap-gate corpus rationale
restored where the sweep over-cut). Comment-only proven: all 3742
wwbuild workdir .s byte-identical before/after; test-commit and
test-byteid (161 lang + 1399 data, 0 pinned-divergent) green.
2026-08-08 21:40:23 +09:00

70 lines
2.4 KiB
Plaintext

// A []T (slice-typed) VALUE stored through a
// WHOLE-deref lhs `*p = sliceval` must move the full 24B {ptr,len,cap} header
// (ref/hare/rt/ensure.ha:4-8), not just {ptr}, migrated from
// test/wcc/944_deref_slice_store_run.c (project #79). The `*p = v` deref-store
// arm was kind-gated on str ONLY; a slice fell to the 1-word default and
// silently DROPPED len+cap. str IS []u8 since Phase 2 (#1), so the str 3-word
// stash+store machinery applies to slices verbatim; the fix widens the gate
// from `str` to `str || slice`. SYMMETRIC across both stages (cs==ww,
// byte-id-BLIND), so only a store->read ROUNDTRIP catches it.
//
// cap != len in every row so a dropped len OR cap is caught.
package deref_slice_store_test;
type box = struct { s: []u8 };
@test fn d_slice_direct() void = {
// A — `*pp = p`, read back via the DIRECT local `dst`. dst is POISONED
// first with a different slice q (len=4,cap=5) via a PROVEN 3-word store
// (`dst = q`, NOT the site under test); a 1-word `*pp=p` leaves q's cap=5,
// the fix lands 8.
let hb: [8]u8; hb[0] = 104u8;
let p: []u8; p.ptr = &hb[0]; p.len = 2; p.cap = 8;
let qb: [8]u8;
let q: []u8; q.ptr = &qb[0]; q.len = 4; q.cap = 5;
let dst: []u8 = q;
let pp: *[]u8 = &dst;
*pp = p;
assert(dst.cap: i32 == 8);
assert(dst.len: i32 == 2);
assert(dst[0] == 104u8);
};
@test fn d_slice_thru() void = {
// B — same store, read back THROUGH the pointer via the 3-word field-deref
// read `(*pp).cap`/`.len` (already 3-word), confirming the stored header
// survives a pointer-side read.
let hb: [8]u8; hb[0] = 104u8;
let p: []u8; p.ptr = &hb[0]; p.len = 2; p.cap = 8;
let qb: [8]u8;
let q: []u8; q.ptr = &qb[0]; q.len = 4; q.cap = 5;
let dst: []u8 = q;
let pp: *[]u8 = &dst;
*pp = p;
assert((*pp).cap: i32 == 8);
assert((*pp).len: i32 == 2);
};
@test fn d_str_control() void = {
// C — control str-deref: the str arm the fix widens around must still land
// len=5 (regression guard). Poison d="xy" then `*pp="hello"`.
let d: str = "xy";
let pp: *str = &d;
*pp = "hello";
assert(d.len: i32 == 5);
};
@test fn d_field_control() void = {
// D — control (*p).field: explicit-deref field store, a separate
// already-3-word branch. `(*pb).s = p` into a struct{s:[]u8}.
let hb: [8]u8; hb[0] = 104u8;
let p: []u8; p.ptr = &hb[0]; p.len = 2; p.cap = 8;
let b: box;
let pb: *box = &b;
(*pb).s = p;
assert(b.s.cap: i32 == 8);
assert(b.s.len: i32 == 2);
assert(b.s[0] == 104u8);
};