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:
@@ -544,7 +544,11 @@ fn cgtryprop(c: *cgen, n: *syntax.node) void = {
|
||||
for (p != nil) {
|
||||
if (variantiserror(u, i)) {
|
||||
let j: i32 = flatvariantidxt(r, p.type_, false);
|
||||
if (j < 0) { j = 0; };
|
||||
if (j < 0) {
|
||||
let mtp: str = "tryprop: error variant missing from fn return union (rule 7)\n";
|
||||
os.write(2, mtp.ptr, mtp.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (j != i) {
|
||||
let skip: str = mklabel(c, "tryprop_skip");
|
||||
emitline("\tCMPQ\t$");
|
||||
@@ -796,7 +800,11 @@ fn cgtypetest(c: *cgen, n: *syntax.node) void = {
|
||||
emitline("\tJNE\t");
|
||||
};
|
||||
} else {
|
||||
if (want < 0) { want = 0; };
|
||||
if (want < 0) {
|
||||
let mtt: str = "tagged typetest: type not in union (rule 7)\n";
|
||||
os.write(2, mtt.ptr, mtt.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tCMPQ\t$");
|
||||
emitint(want: i64);
|
||||
emitline(", AX\n");
|
||||
@@ -982,7 +990,11 @@ fn cgtypeassert(c: *cgen, n: *syntax.node) void = {
|
||||
emitlabel(okl);
|
||||
return;
|
||||
};
|
||||
if (want < 0) { want = 0; };
|
||||
if (want < 0) {
|
||||
let mtt: str = "tagged typetest: type not in union (rule 7)\n";
|
||||
os.write(2, mtt.ptr, mtt.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tMOVQ\t");
|
||||
emitoff(scrutoff: i64);
|
||||
emitline("(BP), AX\n");
|
||||
@@ -3115,7 +3127,12 @@ fn matcharmwant(c: *cgen, scrutt: *syntax.node, pat: *syntax.node) i32 = {
|
||||
r = flatvariantidxt(scrutt.type_: *syntax.tinfo, pattype, false);
|
||||
};
|
||||
};
|
||||
if (r >= 0) { want = r; };
|
||||
if (r < 0) {
|
||||
let mmt: str = "tagged match: case type not in union (rule 7)\n";
|
||||
os.write(2, mmt.ptr, mmt.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
want = r;
|
||||
};
|
||||
};
|
||||
return want;
|
||||
@@ -10439,7 +10456,11 @@ fn cgassign(c: *cgen, n: *syntax.node) void = {
|
||||
if (viaptr) { emitline("\tMOVQ\t(BX), BX\n"); };
|
||||
emitline("\tPOPQ\tAX\n");
|
||||
let v58tag: i32 = taggedvariantindext(c, fi.tnode.type_: *syntax.tinfo, n.rhs);
|
||||
if (v58tag < 0) { v58tag = 0; };
|
||||
if (v58tag < 0) {
|
||||
let mws: str = "tagged widen: no variant tag for source (rule 7)\n";
|
||||
os.write(2, mws.ptr, mws.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tMOVQ\t$");
|
||||
emitint(v58tag: i64);
|
||||
emitline(", ");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -4016,7 +4016,11 @@ fn cgwidentagremap(c: *cgen, du: *syntax.tinfo, su: *syntax.tinfo, slot_off: i32
|
||||
let idx: i32 = 0;
|
||||
for (p != nil) {
|
||||
let di: i32 = flatvariantidxt(dt, p.type_, false);
|
||||
if (di < 0) { di = 0; };
|
||||
if (di < 0) {
|
||||
let mrm: str = "tagged widen: source variant missing from dst union (rule 7)\n";
|
||||
os.write(2, mrm.ptr, mrm.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (di != idx) { identity = false; p = nil; }
|
||||
else { p = p.tnext; idx += 1; };
|
||||
};
|
||||
@@ -4030,7 +4034,11 @@ fn cgwidentagremap(c: *cgen, du: *syntax.tinfo, su: *syntax.tinfo, slot_off: i32
|
||||
for (p != nil) {
|
||||
let next: str = mklabel(c, "remap_next");
|
||||
let di: i32 = flatvariantidxt(dt, p.type_, false);
|
||||
if (di < 0) { di = 0; };
|
||||
if (di < 0) {
|
||||
let mrm: str = "tagged widen: source variant missing from dst union (rule 7)\n";
|
||||
os.write(2, mrm.ptr, mrm.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tCMPQ\t$");
|
||||
emitint(idx: i64);
|
||||
emitline(", AX\n");
|
||||
@@ -5126,7 +5134,11 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *syntax.tinfo, src: *syntax.node, slot_of
|
||||
zoff += 8;
|
||||
};
|
||||
let tag: i32 = taggedvariantindext(c, dt, src);
|
||||
if (tag < 0) { tag = 0; };
|
||||
if (tag < 0) {
|
||||
let mws: str = "tagged widen: no variant tag for source (rule 7)\n";
|
||||
os.write(2, mws.ptr, mws.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
if (src.kind == syntax.nkind.N_STRUCTLIT) {
|
||||
// #23: delegate to the single fill path. The
|
||||
// inline field loop this replaces was a
|
||||
@@ -5206,7 +5218,11 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *syntax.tinfo, src: *syntax.node, slot_of
|
||||
emitoff((slot_off + 24): i64);
|
||||
emitline("(BP)\n");
|
||||
let tag: i32 = taggedvariantindext(c, dt, src);
|
||||
if (tag < 0) { tag = 0; };
|
||||
if (tag < 0) {
|
||||
let mws: str = "tagged widen: no variant tag for source (rule 7)\n";
|
||||
os.write(2, mws.ptr, mws.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tMOVQ\t$");
|
||||
emitint(tag: i64);
|
||||
emitline(", ");
|
||||
@@ -5309,7 +5325,11 @@ fn cgwidentaggedstorebp(c: *cgen, dst: *syntax.tinfo, src: *syntax.node, slot_of
|
||||
};
|
||||
};
|
||||
let tag: i32 = taggedvariantindext(c, dt, src);
|
||||
if (tag < 0) { tag = 0; };
|
||||
if (tag < 0) {
|
||||
let mws: str = "tagged widen: no variant tag for source (rule 7)\n";
|
||||
os.write(2, mws.ptr, mws.len: u64);
|
||||
os.exit(1);
|
||||
};
|
||||
emitline("\tMOVQ\t$");
|
||||
emitint(tag: i64);
|
||||
emitline(", ");
|
||||
|
||||
Reference in New Issue
Block a user