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:
@@ -13296,7 +13296,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -13296,7 +13296,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;
|
||||
|
||||
Reference in New Issue
Block a user