wcc/check: #24-sib reject array-payload tagged-union construction, both stages
Constructing an array-typed payload into a tagged-union variant silently dropped it (cstage MOVQ $0 -> returns 0; wwstage match-loud only). Reject the construct when the selected variant chases to TY_ARRAY (target TY_TAGGED, non-tagged source). tagged-struct/slice/scalar/str variants and the array TYPE-decl stay legal. Faithful array-into-box block-store deferred (#6). test/wcc/834 (new) + Makefile.
This commit is contained in:
@@ -14526,6 +14526,45 @@ fn errnotassign(c: *checker, dst: *node, src: *node, where: str) void = {
|
||||
c.errs += 1;
|
||||
};
|
||||
|
||||
// taggedarrayvariantctor — #5/#60: true when `src` is boxed into the
|
||||
// tagged union `dst` via a variant that chases to TY_ARRAY. The array-
|
||||
// payload box is unwired in cgen (cstage zero-filled the slot at box
|
||||
// materialization — a silent MOVQ $0 payload drop; wwstage only loud at
|
||||
// the dead match arm, errbadcase:4107). Reject the CONSTRUCT until the
|
||||
// faithful array-block-store lands (deferred task #6). The tagged TYPE-
|
||||
// decl with an array variant stays legal — test 944 declares
|
||||
// (void|size|[5]size) and boxes only the narrow `size` variant — only
|
||||
// the array-variant box is refused. Mirrors the concrete→tagged variant
|
||||
// select in isassignable (:3859) and cstage tagged_array_variant so the
|
||||
// variant chosen here is the one the box would materialize.
|
||||
fn taggedarrayvariantctor(c: *checker, dst: *node, src: *node) bool = {
|
||||
if (dst == nil) { return false; };
|
||||
if (src == nil) { return false; };
|
||||
let du: *node = resolvealias(c, unwrapbang(dst));
|
||||
let su: *node = resolvealias(c, unwrapbang(src));
|
||||
if (du == nil) { return false; };
|
||||
if (du.kind != nkind.N_TTAGGED) { return false; };
|
||||
if (su != nil) { if (su.kind == nkind.N_TTAGGED) { return false; }; };
|
||||
let v: *node = du.list;
|
||||
for (v != nil) {
|
||||
let vspread: bool = (v.op == tkind.TK_ELLIPSIS);
|
||||
let vu: *node = resolvealias(c, unwrapbang(v));
|
||||
let vtagged: bool = false;
|
||||
if (vu != nil) { if (vu.kind == nkind.N_TTAGGED) { vtagged = true; }; };
|
||||
if (vtagged && !vspread) {
|
||||
if (typeeqast(v, src)) { return false; };
|
||||
} else {
|
||||
let innerconf: bool = false;
|
||||
if (isassignable(c, v, src, &innerconf)) {
|
||||
if (vu != nil) { if (vu.kind == nkind.N_TARRAY) { return true; }; };
|
||||
return false;
|
||||
};
|
||||
};
|
||||
v = v.next;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
// checkarrlitfits — #130/#251 array-init accept-if-fits, shared by the
|
||||
// let / def / struct-field init sites. arrtn is the declared [N]T type
|
||||
// node, rhs the N_ARRLIT. Per element: foldable int/rune literal →
|
||||
@@ -15098,6 +15137,13 @@ fn checkletassign(c: *checker, n: *node) void = {
|
||||
if (!ok) { if (assignableaddrfn(c, n.lhs, n.rhs)) { ok = true; }; };
|
||||
if (!conf) { return; };
|
||||
if (!ok) { errnotassign(c, n.lhs, src, "let"); };
|
||||
// #5/#60: reject boxing an array payload into a tagged variant. cerr
|
||||
// alone does NOT fail the build — bump c.errs (errnotassign:4245 idiom).
|
||||
if (taggedarrayvariantctor(c, n.lhs, src)) {
|
||||
cerr("array-typed tagged-union variant construction unwired — reject (task #5 / #60)\n");
|
||||
c.errs += 1;
|
||||
return;
|
||||
};
|
||||
// #258: `let s: []T = arr` borrows the array as a full slice. The
|
||||
// desugar lowers to a runtime `arr[0:len]` N_SLICE, so it only
|
||||
// applies to LOCAL lets (a fn body executes the borrow). A MODULE-
|
||||
@@ -15156,6 +15202,13 @@ fn checkretassign(c: *checker, n: *node) void = {
|
||||
if (!ok) { if (assignableaddrfn(c, c.fnret, n.lhs)) { ok = true; }; };
|
||||
if (!conf) { return; };
|
||||
if (!ok) { errnotassign(c, c.fnret, src, "return"); };
|
||||
// #5/#60: reject returning an array payload into a tagged variant. cerr
|
||||
// alone does NOT fail the build — bump c.errs (errnotassign:4245 idiom).
|
||||
if (taggedarrayvariantctor(c, c.fnret, src)) {
|
||||
cerr("array-typed tagged-union variant construction unwired — reject (task #5 / #60)\n");
|
||||
c.errs += 1;
|
||||
return;
|
||||
};
|
||||
// #258: `return arr` borrows the array as a full slice.
|
||||
// #31/#33: bare array-literal has no backing — loud-reject
|
||||
// (supported only at a `let`).
|
||||
|
||||
@@ -4245,6 +4245,45 @@ fn errnotassign(c: *checker, dst: *node, src: *node, where: str) void = {
|
||||
c.errs += 1;
|
||||
};
|
||||
|
||||
// taggedarrayvariantctor — #5/#60: true when `src` is boxed into the
|
||||
// tagged union `dst` via a variant that chases to TY_ARRAY. The array-
|
||||
// payload box is unwired in cgen (cstage zero-filled the slot at box
|
||||
// materialization — a silent MOVQ $0 payload drop; wwstage only loud at
|
||||
// the dead match arm, errbadcase:4107). Reject the CONSTRUCT until the
|
||||
// faithful array-block-store lands (deferred task #6). The tagged TYPE-
|
||||
// decl with an array variant stays legal — test 944 declares
|
||||
// (void|size|[5]size) and boxes only the narrow `size` variant — only
|
||||
// the array-variant box is refused. Mirrors the concrete→tagged variant
|
||||
// select in isassignable (:3859) and cstage tagged_array_variant so the
|
||||
// variant chosen here is the one the box would materialize.
|
||||
fn taggedarrayvariantctor(c: *checker, dst: *node, src: *node) bool = {
|
||||
if (dst == nil) { return false; };
|
||||
if (src == nil) { return false; };
|
||||
let du: *node = resolvealias(c, unwrapbang(dst));
|
||||
let su: *node = resolvealias(c, unwrapbang(src));
|
||||
if (du == nil) { return false; };
|
||||
if (du.kind != nkind.N_TTAGGED) { return false; };
|
||||
if (su != nil) { if (su.kind == nkind.N_TTAGGED) { return false; }; };
|
||||
let v: *node = du.list;
|
||||
for (v != nil) {
|
||||
let vspread: bool = (v.op == tkind.TK_ELLIPSIS);
|
||||
let vu: *node = resolvealias(c, unwrapbang(v));
|
||||
let vtagged: bool = false;
|
||||
if (vu != nil) { if (vu.kind == nkind.N_TTAGGED) { vtagged = true; }; };
|
||||
if (vtagged && !vspread) {
|
||||
if (typeeqast(v, src)) { return false; };
|
||||
} else {
|
||||
let innerconf: bool = false;
|
||||
if (isassignable(c, v, src, &innerconf)) {
|
||||
if (vu != nil) { if (vu.kind == nkind.N_TARRAY) { return true; }; };
|
||||
return false;
|
||||
};
|
||||
};
|
||||
v = v.next;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
// checkarrlitfits — #130/#251 array-init accept-if-fits, shared by the
|
||||
// let / def / struct-field init sites. arrtn is the declared [N]T type
|
||||
// node, rhs the N_ARRLIT. Per element: foldable int/rune literal →
|
||||
@@ -4817,6 +4856,13 @@ fn checkletassign(c: *checker, n: *node) void = {
|
||||
if (!ok) { if (assignableaddrfn(c, n.lhs, n.rhs)) { ok = true; }; };
|
||||
if (!conf) { return; };
|
||||
if (!ok) { errnotassign(c, n.lhs, src, "let"); };
|
||||
// #5/#60: reject boxing an array payload into a tagged variant. cerr
|
||||
// alone does NOT fail the build — bump c.errs (errnotassign:4245 idiom).
|
||||
if (taggedarrayvariantctor(c, n.lhs, src)) {
|
||||
cerr("array-typed tagged-union variant construction unwired — reject (task #5 / #60)\n");
|
||||
c.errs += 1;
|
||||
return;
|
||||
};
|
||||
// #258: `let s: []T = arr` borrows the array as a full slice. The
|
||||
// desugar lowers to a runtime `arr[0:len]` N_SLICE, so it only
|
||||
// applies to LOCAL lets (a fn body executes the borrow). A MODULE-
|
||||
@@ -4875,6 +4921,13 @@ fn checkretassign(c: *checker, n: *node) void = {
|
||||
if (!ok) { if (assignableaddrfn(c, c.fnret, n.lhs)) { ok = true; }; };
|
||||
if (!conf) { return; };
|
||||
if (!ok) { errnotassign(c, c.fnret, src, "return"); };
|
||||
// #5/#60: reject returning an array payload into a tagged variant. cerr
|
||||
// alone does NOT fail the build — bump c.errs (errnotassign:4245 idiom).
|
||||
if (taggedarrayvariantctor(c, c.fnret, src)) {
|
||||
cerr("array-typed tagged-union variant construction unwired — reject (task #5 / #60)\n");
|
||||
c.errs += 1;
|
||||
return;
|
||||
};
|
||||
// #258: `return arr` borrows the array as a full slice.
|
||||
// #31/#33: bare array-literal has no backing — loud-reject
|
||||
// (supported only at a `let`).
|
||||
|
||||
@@ -14526,6 +14526,45 @@ fn errnotassign(c: *checker, dst: *node, src: *node, where: str) void = {
|
||||
c.errs += 1;
|
||||
};
|
||||
|
||||
// taggedarrayvariantctor — #5/#60: true when `src` is boxed into the
|
||||
// tagged union `dst` via a variant that chases to TY_ARRAY. The array-
|
||||
// payload box is unwired in cgen (cstage zero-filled the slot at box
|
||||
// materialization — a silent MOVQ $0 payload drop; wwstage only loud at
|
||||
// the dead match arm, errbadcase:4107). Reject the CONSTRUCT until the
|
||||
// faithful array-block-store lands (deferred task #6). The tagged TYPE-
|
||||
// decl with an array variant stays legal — test 944 declares
|
||||
// (void|size|[5]size) and boxes only the narrow `size` variant — only
|
||||
// the array-variant box is refused. Mirrors the concrete→tagged variant
|
||||
// select in isassignable (:3859) and cstage tagged_array_variant so the
|
||||
// variant chosen here is the one the box would materialize.
|
||||
fn taggedarrayvariantctor(c: *checker, dst: *node, src: *node) bool = {
|
||||
if (dst == nil) { return false; };
|
||||
if (src == nil) { return false; };
|
||||
let du: *node = resolvealias(c, unwrapbang(dst));
|
||||
let su: *node = resolvealias(c, unwrapbang(src));
|
||||
if (du == nil) { return false; };
|
||||
if (du.kind != nkind.N_TTAGGED) { return false; };
|
||||
if (su != nil) { if (su.kind == nkind.N_TTAGGED) { return false; }; };
|
||||
let v: *node = du.list;
|
||||
for (v != nil) {
|
||||
let vspread: bool = (v.op == tkind.TK_ELLIPSIS);
|
||||
let vu: *node = resolvealias(c, unwrapbang(v));
|
||||
let vtagged: bool = false;
|
||||
if (vu != nil) { if (vu.kind == nkind.N_TTAGGED) { vtagged = true; }; };
|
||||
if (vtagged && !vspread) {
|
||||
if (typeeqast(v, src)) { return false; };
|
||||
} else {
|
||||
let innerconf: bool = false;
|
||||
if (isassignable(c, v, src, &innerconf)) {
|
||||
if (vu != nil) { if (vu.kind == nkind.N_TARRAY) { return true; }; };
|
||||
return false;
|
||||
};
|
||||
};
|
||||
v = v.next;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
// checkarrlitfits — #130/#251 array-init accept-if-fits, shared by the
|
||||
// let / def / struct-field init sites. arrtn is the declared [N]T type
|
||||
// node, rhs the N_ARRLIT. Per element: foldable int/rune literal →
|
||||
@@ -15098,6 +15137,13 @@ fn checkletassign(c: *checker, n: *node) void = {
|
||||
if (!ok) { if (assignableaddrfn(c, n.lhs, n.rhs)) { ok = true; }; };
|
||||
if (!conf) { return; };
|
||||
if (!ok) { errnotassign(c, n.lhs, src, "let"); };
|
||||
// #5/#60: reject boxing an array payload into a tagged variant. cerr
|
||||
// alone does NOT fail the build — bump c.errs (errnotassign:4245 idiom).
|
||||
if (taggedarrayvariantctor(c, n.lhs, src)) {
|
||||
cerr("array-typed tagged-union variant construction unwired — reject (task #5 / #60)\n");
|
||||
c.errs += 1;
|
||||
return;
|
||||
};
|
||||
// #258: `let s: []T = arr` borrows the array as a full slice. The
|
||||
// desugar lowers to a runtime `arr[0:len]` N_SLICE, so it only
|
||||
// applies to LOCAL lets (a fn body executes the borrow). A MODULE-
|
||||
@@ -15156,6 +15202,13 @@ fn checkretassign(c: *checker, n: *node) void = {
|
||||
if (!ok) { if (assignableaddrfn(c, c.fnret, n.lhs)) { ok = true; }; };
|
||||
if (!conf) { return; };
|
||||
if (!ok) { errnotassign(c, c.fnret, src, "return"); };
|
||||
// #5/#60: reject returning an array payload into a tagged variant. cerr
|
||||
// alone does NOT fail the build — bump c.errs (errnotassign:4245 idiom).
|
||||
if (taggedarrayvariantctor(c, c.fnret, src)) {
|
||||
cerr("array-typed tagged-union variant construction unwired — reject (task #5 / #60)\n");
|
||||
c.errs += 1;
|
||||
return;
|
||||
};
|
||||
// #258: `return arr` borrows the array as a full slice.
|
||||
// #31/#33: bare array-literal has no backing — loud-reject
|
||||
// (supported only at a `let`).
|
||||
|
||||
Reference in New Issue
Block a user