w6c: variant-tag miss is loud, never tag 0 (rule 7)

Every variant-index lookup miss (-1) was silently clamped to tag 0
across both stages: tagged return (value + bare-void), widen store
(struct/slice/str/float/scalar arms + push fast path + field store),
widen tag-remap (identity scan + emit loop), match case compare,
is/as typetest, tryprop error remap, and the alloc-nomem propagation
(clamped to 1). All misses are checker-rejected upstream today, so
the clamps were dead -- but any future checker/cgen seam gap would
mis-tag silently (wrong arm, wrong error, false success). Rule 7:
each site now hard-stops with a per-construct diagnostic; nullable
arms keep their raw -1 by design (a miss encodes the void polarity
for `case null`). Corpus asm byte-unchanged; bootstrap fixed point
holds.
This commit is contained in:
2026-08-09 00:12:21 +09:00
parent 94928470bc
commit 57d33acd1f
4 changed files with 140 additions and 34 deletions

View File

@@ -1211,8 +1211,12 @@ fn cgreturn(c: *cgen, n: *syntax.node) void = {
emitline("\tMOVQ\t$0, R8\n");
};
};};};
if (idx < 0) {
let mtag: str = "tagged return: no variant tag for return value (rule 7)\n";
os.write(2, mtag.ptr, mtag.len: u64);
os.exit(1);
};
emitline("\tMOVQ\t$");
if (idx < 0) { idx = 0; };
emitint(idx: i64);
emitline(", AX\n");
emitline("\tMOVQ\tBP, SP\n");
@@ -1847,7 +1851,11 @@ fn cgreturn(c: *cgen, n: *syntax.node) void = {
if (sretretsize(c, c.fnret) > 0) {
let sa38: i32 = localfind(c, "@sretarg");
let vidx38: i32 = voidvariantindex(c.fnret);
if (vidx38 < 0) { vidx38 = 0; };
if (vidx38 < 0) {
let mvd: str = "tagged return: no void variant (rule 7)\n";
os.write(2, mvd.ptr, mvd.len: u64);
os.exit(1);
};
emitline("\tMOVQ\t");
emitoff(sa38: i64);
emitline("(BP), BX\n");
@@ -1868,7 +1876,11 @@ fn cgreturn(c: *cgen, n: *syntax.node) void = {
emitline("\tMOVQ\t$0, AX\n");
} else {
let idx: i32 = voidvariantindex(c.fnret);
if (idx < 0) { idx = 0; };
if (idx < 0) {
let mvd: str = "tagged return: no void variant (rule 7)\n";
os.write(2, mvd.ptr, mvd.len: u64);
os.exit(1);
};
emitline("\tMOVQ\t$");
emitint(idx: i64);
emitline(", AX\n");
@@ -2301,7 +2313,11 @@ fn cgletbody(c: *cgen, n: *syntax.node, off: i32) void = {
nidx2 += 1;
};
}; };
if (nidx < 0) { nidx = 1; };
if (nidx < 0) {
let mnm: str = "tryprop: no nomem variant in fn return union (rule 7)\n";
os.write(2, mnm.ptr, mnm.len: u64);
os.exit(1);
};
emitline("\tMOVQ\t$");
emitint(nidx: i64);
emitline(", AX\n");