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.
77 lines
2.6 KiB
Plaintext
77 lines
2.6 KiB
Plaintext
// A sub-slice `base[lo:hi]` must set its capacity word to
|
|
// base_cap - lo (storage remaining to the underlying end; Go/Hare-identical),
|
|
// NOT hi - lo (the new length), migrated from test/wcc/942_subslice_cap_run.c
|
|
// (task #20). base_cap is the array length N for [N]T, or the carried .capacity
|
|
// for a slice/str base. Cite (drew): harec ref/harec/src/eval.c:1017 (slice cap
|
|
// -= start), eval.c:1024 (array cap = length - start), check.c:596 (cap>=len),
|
|
// ref/hare/rt/ensure.ha:4-8 (capacity is a distinct field).
|
|
//
|
|
// Before the fix BOTH stages emitted cap = hi - lo (== len). Every row picks a
|
|
// shape where base_cap - lo != hi - lo, so a stale `cap = len` stage is
|
|
// observably wrong (cap reads hi-lo, or the append row reallocs instead of
|
|
// filling the base's spare). cap != len in every row.
|
|
|
|
package subslice_cap_test;
|
|
|
|
@test fn subslice_array_hilt_n() void = {
|
|
// A — array base, hi < N. cap = N(8) - lo(1) = 7 != len(2).
|
|
let a: [8]u8;
|
|
let i: i32 = 0;
|
|
for (i < 8) { a[i] = (20 + i): u8; i += 1; };
|
|
let s: []u8 = a[1:3];
|
|
assert(s.cap: i32 == 7);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 21u8);
|
|
};
|
|
|
|
@test fn subslice_slice_spare_cap() void = {
|
|
// B — slice base with spare cap. cap = base.cap(8) - lo(1) = 7 != len(3);
|
|
// base.cap is read from the header +16, not re-derived.
|
|
let a: [8]u8;
|
|
let i: i32 = 0;
|
|
for (i < 8) { a[i] = (40 + i): u8; i += 1; };
|
|
let p: []u8; p.ptr = &a[0]; p.len = 6; p.cap = 8;
|
|
let s: []u8 = p[1:4];
|
|
assert(s.cap: i32 == 7);
|
|
assert(s.len: i32 == 3);
|
|
assert(s[0] == 41u8);
|
|
};
|
|
|
|
@test fn subslice_str_base() void = {
|
|
// C — str base (str[lo:hi] yields str, real .capacity, no downgrade).
|
|
// cap = sb.cap(5) - lo(1) = 4 != len(2).
|
|
let sb: str = "hello";
|
|
let s: str = sb[1:3];
|
|
assert(s.cap: i32 == 4);
|
|
assert(s.len: i32 == 2);
|
|
assert(s[0] == 101u8);
|
|
};
|
|
|
|
@test fn subslice_append_no_realloc() void = {
|
|
// D — append-no-realloc (strongest). s = buf[1:3] has cap 7 > len 2, so
|
|
// append(s,99) fills buf's spare at lo+len = 3. A cap=len stage sees
|
|
// len==cap (full) and reallocs, leaving buf[3] == 0.
|
|
let buf: [8]u8;
|
|
let i: i32 = 0;
|
|
for (i < 8) { buf[i] = 0u8; i += 1; };
|
|
let s: []u8 = buf[1:3];
|
|
append(s, 99u8);
|
|
assert(s.cap: i32 == 7);
|
|
assert(s.len: i32 == 3);
|
|
assert(s[2] == 99u8);
|
|
assert(buf[3] == 99u8);
|
|
};
|
|
|
|
@test fn subslice_hidefault_spare_cap() void = {
|
|
// E — hi-default with spare cap. p{len=6,cap=8}; `p[2:]` defaults hi to
|
|
// base.len=6, so len = 4, but cap = base.cap(8) - lo(2) = 6 != len.
|
|
let a: [8]u8;
|
|
let i: i32 = 0;
|
|
for (i < 8) { a[i] = (60 + i): u8; i += 1; };
|
|
let p: []u8; p.ptr = &a[0]; p.len = 6; p.cap = 8;
|
|
let s: []u8 = p[2:];
|
|
assert(s.cap: i32 == 6);
|
|
assert(s.len: i32 == 4);
|
|
assert(s[0] == 62u8);
|
|
};
|