wcc_ww/check: infer named-struct element for arrlit->slice assignability (fix #19)

wwstage over-rejected an inline `let g: []pt = [pt{..}, pt{..}]`. The
N_ARRLIT exprtype arm inferred its element type from the first element,
an N_STRUCTLIT, whose exprtype arm deliberately returns the struct BODY
(N_TSTRUCT) per #66. The array->slice isassignable arm then typeeqast's
the declared element (N_TNAME "pt") against that body and bails on the
TNAME-vs-TSTRUCT kind mismatch -> confident-false -> reject. The reject
is a KIND mismatch, not a nominal-compare weakness: typeeqast is already
streq-keyed for N_TNAME.

Narrow fix: when the first arrlit element is a named struct literal,
capture the NAMED type (mktname) so su.lhs matches the declared N_TNAME
shape, mirroring cstage's element inference. typeeqast and the
N_STRUCTLIT #66 body-return are untouched; non-named elements keep the
existing first-element shape. e.type_ via tinfofornode still resolves
[N]pt for cgen, so cstage/wwstage stay byte-identical.

Test 687 gains struct_pt (sum+len+cap == 14), struct_3f (mixed-width
u8/i64/i32 field offsets == 23), and struct_arrvar_local (the
array-VARIABLE form still accepts+runs; local scope since the
module-scope variable form is the deferred #22 link gap).
This commit is contained in:
2026-06-03 22:51:24 +09:00
parent 8dda8ea76c
commit 1e081e28c6
4 changed files with 116 additions and 3 deletions

View File

@@ -2929,7 +2929,25 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
};
if (!skip) {
let t: *node = exprtype(c, it, nil);
if (elt == nil) { elt = t; };
if (elt == nil) {
// #19: N_STRUCTLIT exprtype returns the struct BODY
// (N_TSTRUCT) per #66, but the array->slice
// isassignable arm typeeqast's the declared element
// N_TNAME against this element shape — a TNAME-vs-
// TSTRUCT kind mismatch reads confident-false and
// rejects. cstage infers the NAMED type here. Capture
// the named type for a named struct literal so su.lhs
// is the same N_TNAME shape (typeeqast is already
// streq-keyed for TNAME). Non-named elements keep the
// existing first-element shape.
if (it.kind == nkind.N_STRUCTLIT
&& it.lhs != nil
&& it.lhs.kind == nkind.N_IDENT) {
elt = mktname(c, it.lhs.str);
} else {
elt = t;
};
};
count += 1u64;
};
it = it.next;