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.
65 lines
1.9 KiB
Plaintext
65 lines
1.9 KiB
Plaintext
// `len(t.N)` where t is a tuple and t.N is a
|
|
// slice/str-typed element, migrated from test/wcc/903_tuple_elem_slice_len_run.c
|
|
// (#235). The len() builtin special-cased only a PLAIN N_IDENT slice operand
|
|
// and an array operand; every other shape fell back to a bare `cgexpr(operand)`,
|
|
// which for a slice leaves AX=.ptr. A tuple-element read (`t.N`) loads only
|
|
// AX=.ptr, so `len(t.N)` returned the slice's .ptr word AS the length — a SILENT
|
|
// miscompile, gate-blind because the bootstrap never does len() on a
|
|
// slice-typed tuple element. The fix (both stages, byte-id) loads the element's
|
|
// .len word directly at BP + tuple_off + element_off + 8. Every element has a
|
|
// DISTINCT length so a dropped/wrong field is caught. Tuples are slice/str-ONLY
|
|
// here — a leading scalar element exercises a separate mixed-tuple sret
|
|
// divergence (filed apart, out of scope).
|
|
|
|
package tuple_elem_slice_len_test;
|
|
|
|
fn mk2() ([]u8, []u8) = {
|
|
let a: []u8; a.len = 3; a.cap = 7;
|
|
let b: []u8; b.len = 5; b.cap = 9;
|
|
return (a, b);
|
|
};
|
|
|
|
fn mk3() ([]u8, []u8, []u8) = {
|
|
let a: []u8; a.len = 3; a.cap = 7;
|
|
let b: []u8; b.len = 5; b.cap = 9;
|
|
let c: []u8; c.len = 11; c.cap = 13;
|
|
return (a, b, c);
|
|
};
|
|
|
|
fn mksb() (str, []u8) = {
|
|
let s: str = "abcd";
|
|
let b: []u8; b.len = 6; b.cap = 8;
|
|
return (s, b);
|
|
};
|
|
|
|
fn mkbs() ([]u8, str) = {
|
|
let b: []u8; b.len = 7; b.cap = 9;
|
|
let s: str = "hi";
|
|
return (b, s);
|
|
};
|
|
|
|
@test fn two_slice() void = {
|
|
let t: ([]u8, []u8) = mk2();
|
|
assert(len(t.0): i32 == 3);
|
|
assert(len(t.1): i32 == 5);
|
|
};
|
|
|
|
@test fn three_slice() void = {
|
|
let t: ([]u8, []u8, []u8) = mk3();
|
|
assert(len(t.0): i32 == 3);
|
|
assert(len(t.1): i32 == 5);
|
|
assert(len(t.2): i32 == 11);
|
|
};
|
|
|
|
@test fn str_slice() void = {
|
|
let t: (str, []u8) = mksb();
|
|
assert(len(t.0): i32 == 4);
|
|
assert(len(t.1): i32 == 6);
|
|
};
|
|
|
|
@test fn slice_str() void = {
|
|
let t: ([]u8, str) = mkbs();
|
|
assert(len(t.0): i32 == 7);
|
|
assert(len(t.1): i32 == 2);
|
|
};
|