selfhost/cmd/wcc + lib/strings: restore SSoT routing for str/slice tinfo helpers

Phase A.5's tupleelemslot / fieldslotsize hardcoded 16u64 for TY_STR
and 24u64 for TY_SLICE — bypassing the tinfo.size SSoT seeded by
lib/ww/typ.ww:189 (the very pivot they were introduced to consult).
Route those four arms through pt.size / ft.size so #1 (str→24) and
#34 (slice graduation) land as a one-line bump at the seed.

lib/strings/stringstest.ww carried 12 `(cap: u64) * 16u64` strides
missed by #43's sweep over strings.ww + shlex.ww; convert to
`* size(str): u64` so the #42 fold owns the constant. Doc comments
in strings.ww (freeall + splitn) updated to the same SSoT form.

No-op at today's str.size=16 / slice=24: tinfo.size already matches
the literals these arms had baked in. Reviewer's pre/post asm-identity
probe (struct{i64,str,i64} + (i32,str,i32) tuple + bare str) shows
zero-byte diff. 131/131 + 994 + 995 + bootstrap (ww2==ww3==ww4) green.

Forward-link to #1 (str→24B bump) and #64 (sizelint pre-commit gate);
#65 filed for lib/bytes + lib/getopt sibling sites the reviewer
surfaced. Forward of #64 will catch any future regressions of this
class.
This commit is contained in:
2026-05-20 14:55:36 +09:00
parent 9fd79cdc33
commit 03b7336cae
6 changed files with 67 additions and 48 deletions

View File

@@ -1441,7 +1441,7 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
expect_str(t1, 1, "my");
expect_str(t1, 2, "name");
expect_str(t1, 3, "is Drew");
os.free(t1.ptr: *void, (t1.cap: u64) * 16u64);
os.free(t1.ptr: *void, (t1.cap: u64) * size(str): u64);
// ref/hare/strings/tokenize.ha:263 — n > tokens leaves a single
// slot holding the unchanged input (delim not found).
@@ -1449,21 +1449,21 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
let t2: []str = strings.splitn("one", "=", 2);
if (t2.len != 1) { fail(); };
expect_str(t2, 0, "one");
os.free(t2.ptr: *void, (t2.cap: u64) * 16u64);
os.free(t2.ptr: *void, (t2.cap: u64) * size(str): u64);
// n == 1 — single slot holding the whole input as remainder.
signalled = 1742;
let t3: []str = strings.splitn("a b c", " ", 1);
if (t3.len != 1) { fail(); };
expect_str(t3, 0, "a b c");
os.free(t3.ptr: *void, (t3.cap: u64) * 16u64);
os.free(t3.ptr: *void, (t3.cap: u64) * size(str): u64);
// Empty input — empty result.
signalled = 1743;
let t4: []str = strings.splitn("", " ", 5);
if (t4.len != 0) { fail(); };
if (t4.cap > 0) {
os.free(t4.ptr: *void, (t4.cap: u64) * 16u64);
os.free(t4.ptr: *void, (t4.cap: u64) * size(str): u64);
};
// Multi-byte delim set (byte-set semantics per
@@ -1475,7 +1475,7 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
expect_str(t5, 1, "world");
expect_str(t5, 2, "foo");
expect_str(t5, 3, "bar");
os.free(t5.ptr: *void, (t5.cap: u64) * 16u64);
os.free(t5.ptr: *void, (t5.cap: u64) * size(str): u64);
};
@test fn rsplitn_cases() void = {
@@ -1488,7 +1488,7 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
expect_str(t1, 1, "name");
expect_str(t1, 2, "is");
expect_str(t1, 3, "Drew");
os.free(t1.ptr: *void, (t1.cap: u64) * 16u64);
os.free(t1.ptr: *void, (t1.cap: u64) * size(str): u64);
// n > token count — done short-circuit returns toks UN-reversed
// (last-token-first order). Mirrors bytes.rsplitn (Hare's
@@ -1500,14 +1500,14 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
expect_str(t2, 0, "c");
expect_str(t2, 1, "b");
expect_str(t2, 2, "a");
os.free(t2.ptr: *void, (t2.cap: u64) * 16u64);
os.free(t2.ptr: *void, (t2.cap: u64) * size(str): u64);
// n == 1 — single slot holding the whole input as remainder.
signalled = 1752;
let t3: []str = strings.rsplitn("a b c", " ", 1);
if (t3.len != 1) { fail(); };
expect_str(t3, 0, "a b c");
os.free(t3.ptr: *void, (t3.cap: u64) * 16u64);
os.free(t3.ptr: *void, (t3.cap: u64) * size(str): u64);
// delim absent — first next_token yields the entire input as the
// sole token; second iter sees done and short-circuits with the
@@ -1516,7 +1516,7 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
let t4: []str = strings.rsplitn("abc", "=", 5);
if (t4.len != 1) { fail(); };
expect_str(t4, 0, "abc");
os.free(t4.ptr: *void, (t4.cap: u64) * 16u64);
os.free(t4.ptr: *void, (t4.cap: u64) * size(str): u64);
};
@test fn split_cases() void = {
@@ -1530,7 +1530,7 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
expect_str(t1, 2, "name");
expect_str(t1, 3, "is");
expect_str(t1, 4, "Drew");
os.free(t1.ptr: *void, (t1.cap: u64) * 16u64);
os.free(t1.ptr: *void, (t1.cap: u64) * size(str): u64);
// Leading + trailing delim — empty tokens at ends.
signalled = 1761;
@@ -1540,7 +1540,7 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
expect_str(t2, 1, "a");
expect_str(t2, 2, "b");
expect_str(t2, 3, "");
os.free(t2.ptr: *void, (t2.cap: u64) * 16u64);
os.free(t2.ptr: *void, (t2.cap: u64) * size(str): u64);
// Multi-byte delim set, byte-set semantics matching Hare's
// strings::split example at ref/hare/strings/tokenize.ha:235.
@@ -1551,7 +1551,7 @@ fn expect_str(toks: []str, i: i32, want: str) void = {
expect_str(t3, 1, "world");
expect_str(t3, 2, "foo");
expect_str(t3, 3, "bar");
os.free(t3.ptr: *void, (t3.cap: u64) * 16u64);
os.free(t3.ptr: *void, (t3.cap: u64) * size(str): u64);
};
// ---- lpad / rpad -----------------------------------------------------