wcc/check: GAP-A .cap-on-array loud-reject; .ptr-on-array ratified valid (#12)

.cap on a fixed-size array is invalid (Hare has no capacity-read; arrays
can't grow) -> both stages now loud-reject at the checker. wwstage was
silently returning frame garbage for a local array's .cap; cstage typed
it then vaguely rejected at use. Unified to one early checker reject with
an identical diagnostic both stages.

.ptr on a fixed-size array is ratified VALID: array.ptr is &A[0], a
sanctioned ww spelling divergence from Hare; see task #13. The toolchain
already relies on it in 14 backing-pointer sites. WHY-doc added at both
checker .ptr-on-array sites. The def-global .ptr cgen base-selection bug
(#11) is a separate following commit.

Valid-program asm unchanged (byte-id 990-997 8/8); w6c/w6c_ww binaries
move (checker code changed). test/wcc/817 table-driven, model 684.
This commit is contained in:
2026-06-08 17:22:09 +09:00
parent 7b0e09e065
commit 1c87881bda
6 changed files with 373 additions and 0 deletions

View File

@@ -13409,11 +13409,24 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
e.type_ = tinfofornode(c, tn): *void;
return tn;
};
// A fixed array has no capacity word — .cap is
// invalid (drew ruling). cstage check.c errs
// symmetrically. c.errs>0 gates cgen off → build
// fails (the #11 inferarraylen idiom).
if (bu.kind == nkind.N_TARRAY && streq(e.str, "cap")) {
cerr("error: no field 'cap' on a fixed-size array (arrays have no capacity; use .len)\n");
c.errs += 1;
return nil;
};
if (streq(e.str, "cap")) {
let tn: *node = mktname(c, "i32");
e.type_ = tinfofornode(c, tn): *void;
return tn;
};
// rule-9 divergence-doc (drew, task #13): array.ptr ≡
// &A[0], a sanctioned ww spelling / faithful Hare
// desugaring (14 live consumers). KEEP — .ptr valid.
// See .ai/drew-gapa-ptr-ruling.md.
if (streq(e.str, "ptr")) {
let elem: *node = bu.lhs;
if (isstr) { elem = mktname(c, "u8"); };

View File

@@ -3128,11 +3128,24 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
e.type_ = tinfofornode(c, tn): *void;
return tn;
};
// A fixed array has no capacity word — .cap is
// invalid (drew ruling). cstage check.c errs
// symmetrically. c.errs>0 gates cgen off → build
// fails (the #11 inferarraylen idiom).
if (bu.kind == nkind.N_TARRAY && streq(e.str, "cap")) {
cerr("error: no field 'cap' on a fixed-size array (arrays have no capacity; use .len)\n");
c.errs += 1;
return nil;
};
if (streq(e.str, "cap")) {
let tn: *node = mktname(c, "i32");
e.type_ = tinfofornode(c, tn): *void;
return tn;
};
// rule-9 divergence-doc (drew, task #13): array.ptr ≡
// &A[0], a sanctioned ww spelling / faithful Hare
// desugaring (14 live consumers). KEEP — .ptr valid.
// See .ai/drew-gapa-ptr-ruling.md.
if (streq(e.str, "ptr")) {
let elem: *node = bu.lhs;
if (isstr) { elem = mktname(c, "u8"); };

View File

@@ -13409,11 +13409,24 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
e.type_ = tinfofornode(c, tn): *void;
return tn;
};
// A fixed array has no capacity word — .cap is
// invalid (drew ruling). cstage check.c errs
// symmetrically. c.errs>0 gates cgen off → build
// fails (the #11 inferarraylen idiom).
if (bu.kind == nkind.N_TARRAY && streq(e.str, "cap")) {
cerr("error: no field 'cap' on a fixed-size array (arrays have no capacity; use .len)\n");
c.errs += 1;
return nil;
};
if (streq(e.str, "cap")) {
let tn: *node = mktname(c, "i32");
e.type_ = tinfofornode(c, tn): *void;
return tn;
};
// rule-9 divergence-doc (drew, task #13): array.ptr ≡
// &A[0], a sanctioned ww spelling / faithful Hare
// desugaring (14 live consumers). KEEP — .ptr valid.
// See .ai/drew-gapa-ptr-ruling.md.
if (streq(e.str, "ptr")) {
let elem: *node = bu.lhs;
if (isstr) { elem = mktname(c, "u8"); };