Both carriers were already slim: the r76_def_widen_* byte-id legs are owned by the test-data-byteid blanket, 783's positive byte rows by the r78_amp_fn_assign_* fixtures plus that same blanket, and its symmetric non-tagged rejects by the corpus //ww:error fixtures. The unowned remainder is three cstage-only loud-rejects (the 760 narrowing def-ref and 783's two tagged-slot rows); the wwstage over-accepts (no def-init assignability check; #214 void-variant leniency) are documented at the site per the residual audit, never asserted as desired — the rows graduate to //ww:error fixtures when the wwstage side tightens. Bundled: one file, one concern (cstage-reject pins awaiting wwstage graduation).
108 lines
3.8 KiB
Plaintext
108 lines
3.8 KiB
Plaintext
package reject_test;
|
|
|
|
// Cstage-only loud-reject pins, ported from the retired native
|
|
// carriers test/wcc/760_def_widen_const.c and
|
|
// test/wcc/783_amp_fn_assign_run.c. Each row asserts ONLY the cstage
|
|
// reject; the wwstage side over-accepts today and that over-accept is
|
|
// documented here (residual audit, test-infra-v2-residual-20260808),
|
|
// never asserted as desired — these rows graduate to //ww:error
|
|
// corpus fixtures the moment the wwstage checker gains the matching
|
|
// reject.
|
|
//
|
|
// 760 (#113 def_cast_fits): an out-of-range narrowing def-ref must
|
|
// fail the cstage build loud — the const-scoped widen must never
|
|
// become a silent truncation. wwstage has no def-init assignability
|
|
// check at all (pre-existing leanness) and accepts. The r76_def_widen_*
|
|
// byte-id legs the carrier also drove are owned by the
|
|
// test-data-byteid blanket over those fixtures.
|
|
//
|
|
// 783 (#206 gate, tagged rows): the two NEGATIVE tagged-slot rows are
|
|
// cstage-only pending #214 — wwstage's `(X | void)` tagged
|
|
// assignability leniently matches any *fn against the void variant
|
|
// (the accept-INVALID hole; its close is required before wwstage can
|
|
// be the authoritative checker). The positive byte-id rows are owned
|
|
// by the r78_amp_fn_assign_* fixtures plus the test-data-byteid
|
|
// blanket; the symmetric non-tagged rejects by the corpus
|
|
// r783_amp_fn_assign_neg_* //ww:error fixtures.
|
|
|
|
import os;
|
|
import os.exec;
|
|
import strings;
|
|
import testenv;
|
|
import time;
|
|
|
|
fn fail(label: str, why: str) void = {
|
|
let m: str = strings.concat("reject FAIL: ", label, " -- ", why,
|
|
"\n");
|
|
os.write(2, m.ptr, m.len: u64);
|
|
assert(false);
|
|
};
|
|
|
|
fn tmo() time.duration = {
|
|
return (180i64 * (time.second: i64)): time.duration;
|
|
};
|
|
|
|
@test fn defwidennarrow() void = {
|
|
let td: str = testenv.fresh();
|
|
testenv.writefile(strings.concat(td, "/nw.ww"), strings.concat(
|
|
"package main;\n",
|
|
"def BIG_I32: i32 = 70000;\n",
|
|
"def S_I16: i16 = BIG_I32;\n",
|
|
"export fn main() i32 = { let s: i16 = S_I16; ",
|
|
"return s: i32; };\n"));
|
|
let av: []str = [testenv.driver("w6c"), "-o",
|
|
strings.concat(td, "/nw.s"), strings.concat(td, "/nw.ww")];
|
|
let co: testenv.commandout;
|
|
testenv.runcommand(td, td, "narrow", av, tmo(), &co);
|
|
// A deadline kill is not a reject; only a loud EXIT failure is.
|
|
if (co.termination != exec.termination.EXIT) {
|
|
fail("narrow", "w6c did not terminate normally");
|
|
};
|
|
if (co.code == 0) {
|
|
fail("narrow", strings.concat("w6c exited 0 (expected loud ",
|
|
"failure, no silent truncation)"));
|
|
};
|
|
testenv.clean(td);
|
|
};
|
|
|
|
fn cstagerejectrow(label: str, src: str) void = {
|
|
let td: str = testenv.fresh();
|
|
testenv.writefile(strings.concat(td, "/main783.ww"), src);
|
|
let av: []str = [testenv.driver("ww"), "build", "-o", "main783",
|
|
"main783.ww"];
|
|
let co: testenv.commandout;
|
|
testenv.runcommand(td, td, label, av, tmo(), &co);
|
|
if (co.termination != exec.termination.EXIT) {
|
|
fail(label, "cstage build did not terminate normally");
|
|
};
|
|
if (co.code == 0) {
|
|
fail(label, "cstage built but expected reject");
|
|
};
|
|
testenv.clean(td);
|
|
};
|
|
|
|
@test fn ampfnassigntagged() void = {
|
|
// Two same-signature ptr-to-fn variants: a direct &fn is ambiguous
|
|
// and must never silently bind to one.
|
|
cstagerejectrow("neg_ambiguous_tagged", strings.concat(
|
|
"package main;\n",
|
|
"type reader = fn(x: i32) i32;\n",
|
|
"type writer = fn(x: i32) i32;\n",
|
|
"fn myfn(x: i32) i32 = { return x; };\n",
|
|
"fn main() i32 = {\n",
|
|
" let x: (*reader | *writer | void) = &myfn;\n",
|
|
" return 0;\n",
|
|
"};\n"));
|
|
// Laundering a materialized *fn into a (*reader|void) slot:
|
|
// cstage rejects nominally (harec types.c:1039-1066 mirror).
|
|
cstagerejectrow("neg_launder_tagged", strings.concat(
|
|
"package main;\n",
|
|
"type reader = fn(x: i32) i32;\n",
|
|
"fn rd(x: i32) i32 = { return x + 1; };\n",
|
|
"fn main() i32 = {\n",
|
|
" let p = &rd;\n",
|
|
" let s: (*reader | void) = p;\n",
|
|
" return 0;\n",
|
|
"};\n"));
|
|
};
|