selfhost/cmd/wcc: stamp inferred-let decl.lhs (#15 precursor, #43)

checkletassign previously early-returned on `n.lhs == nil`, so an
inferred binding (`let r = expr;`) left decl.lhs unset; exprtype's
N_IDENT branch at check.ww:1550 reads `s.decl.lhs` and so the use
sites lost the inferred type.

Mirrors cstage cmd/wcc/check.c:1477 clet `if (t == NULL && initt)
t = type_default(initt);` and ref/harec/src/check.c:1422
check_expr_binding. cstage carries the let type on Sym.type;
wwstage carries it on decl.lhs — same observable result, byte-id
(rule 10) intact. Defaulting (untyped_int → i32) stays at use
sites in exprtype, not the binding site. Mutation layer matches
#41's installparams parser-decl-mutation precedent at check.ww:2747.

Table-driven test deferred to #44 per the speed-first cadence;
existing 990–997 byte-id corpus implicitly exercises inferred lets.
Context for the capture sweep: #36.
This commit is contained in:
2026-05-22 03:40:52 +09:00
parent 45910ff966
commit faba8b70dd
3 changed files with 36 additions and 3 deletions

View File

@@ -2501,11 +2501,22 @@ fn errnotassign(c: *checker, dst: *node, src: *node, where: str) void = {
fn checkletassign(c: *checker, n: *node) void = {
if (n == nil) { return; };
if (n.lhs == nil) { return; }; // no declared type, nothing to check
if (n.rhs == nil) { return; }; // no init
// hint = nil for A.6.0; A.6.1 will pass n.lhs once STRUCTLIT/ARRLIT
// arms consume it. Plumbing-only at this point.
let src: *node = exprtype(c, n.rhs, nil);
// Inferred binding (`let r = expr;`, no type annotation). Mirror
// cstage cmd/wcc/check.c:1477 clet `if (t == NULL && initt) t =
// type_default(initt);` and ref/harec/src/check.c:1422
// check_expr_binding. wwstage carries the let's type on decl.lhs
// (exprtype N_IDENT at L1546 reads s.decl.lhs); cstage carries it
// on Sym.type — same observable result, rule-10 byte-id holds.
// Defaulting (untyped_int → i32, etc.) is exprtype's job at use
// sites, not the binding site.
if (n.lhs == nil) {
if (src != nil) { n.lhs = src; };
return;
};
if (src == nil) { return; }; // can't infer
// #45: alloc([], n) defers element type to the let-init context
// (Hare-style). exprtype's alloc-slice branch synthesizes