Two more value-observable families ported additively (the .c sources
keep running in $(TESTS); de-dup deferred to fold 6).
932_str_elem_cap -> str_elem_cap_test: a str-element N_INDEX value
read must load the full 24B {ptr,len,cap}, not {ptr,len} (F2); each
shape poisons cap != len so a 2-word read fails the .cap assert.
Template for the 933-939 cap family.
957_size_type -> size_type_test: `size` binds in type position and
coexists with the size(T) operator (#85); a green row is the bind
proof.
59 lines
2.1 KiB
Plaintext
59 lines
2.1 KiB
Plaintext
// str_elem_cap_test — a str-element VALUE read via N_INDEX must load the full
|
|
// 24B {ptr,len,cap} header, not just {ptr,len}, migrated from test/wcc/
|
|
// 932_str_elem_cap_run.c (F2 fold). str is 24B since Phase 2 (#1); pre-F2 the
|
|
// N_INDEX str-element arms dropped the cap word, so reading `.cap` off an
|
|
// indexed str element returned garbage (the missing third word) — cs==ww held,
|
|
// so the 990-997 byte-id gates were GREEN while the runtime was wrong.
|
|
//
|
|
// Each shape POISONS the element so cap != len (a `.cap =` pseudo-field write,
|
|
// no malloc / no import), then observes cap through `let e: str = <index>` (a
|
|
// 3-word copy into the slot) and `e.cap` (an N_IDENT pseudo-field read off the
|
|
// slot). A 2-word read leaves cap = len (N_IDENT base) or a stale slice-cap
|
|
// (fallback base), so the read-back .cap mismatches the poisoned value. .len is
|
|
// the control. The shapes (index base form), not the data, are what vary, so
|
|
// per-shape asserts — this file is the template for the 933-939 cap family.
|
|
|
|
package str_elem_cap_test;
|
|
|
|
type box = struct { items: []str };
|
|
|
|
@test fn sitea_ident_base() void = {
|
|
// N_IDENT base: xs[0] on a local [N]str, constant index. Poison cap=8
|
|
// (len=2); a broken 2-word read leaves cap = len = 2.
|
|
let p: str = "hi";
|
|
p.cap = 8i32;
|
|
let xs: [2]str;
|
|
xs[0] = p;
|
|
let e: str = xs[0];
|
|
assert(e.cap: i32 == 8);
|
|
assert(e.len: i32 == 2);
|
|
};
|
|
|
|
@test fn sitea_var_index() void = {
|
|
// N_IDENT base indexed by a VARIABLE (not a constant) — the index
|
|
// source must not change which words the element load reads.
|
|
let p: str = "hey";
|
|
p.cap = 12i32;
|
|
let xs: [2]str;
|
|
let i: i32 = 1;
|
|
xs[i] = p;
|
|
let e: str = xs[i];
|
|
assert(e.cap: i32 == 12);
|
|
assert(e.len: i32 == 3);
|
|
};
|
|
|
|
@test fn siteb_fallback_base() void = {
|
|
// Fallback base: the element sits behind an N_DOT slice field, so the
|
|
// N_INDEX base isn't a plain ident. Poison cap=9 (len=5); a broken read
|
|
// leaves cap = the slice header's own cap, not the element's.
|
|
let q: str = "world";
|
|
q.cap = 9i32;
|
|
let arr: [2]str;
|
|
arr[0] = q;
|
|
let b: box;
|
|
b.items = arr[0:2];
|
|
let e: str = b.items[0];
|
|
assert(e.cap: i32 == 9);
|
|
assert(e.len: i32 == 5);
|
|
};
|