For-range tuple-destructure binders (for (let (k,v) .. s)) and the tuple massign discard _ were left nil-typed: the for-range binders are N_IDENT use-sites and the _ slot, though unbound, has a real element type. Add a shared stamptuplebinds helper — one lockstep walk distributing an N_TTUPLE's per-element types onto a binder chain — refactoring the existing N_MLET destructure loop into it (behavior identical) and adding N_FORRANGE and N_MASSIGN call-sites. _ is STAMPED with its slot's element type (unbound is not untyped), not exempted. Mirrors harec create_unpack_bindings (ref/harec/src/check.c:1354-1419), the routine harec shares between let-unpack and the for-each header (:2308-2317). A prerequisite for arming the wwstage asserttyped bail. byte-id holds (cgen derives binder/elem widths structurally, never off type_; 990-997 green). Extends the 901 gap-corpus with 901_forrange_tuple.ww + 901_massign_blank.ww.
25 lines
843 B
Plaintext
25 lines
843 B
Plaintext
// 901_forrange_tuple — for-range tuple-destructure binder gap fixture
|
|
// for the 901 asserttyped net (class F). `for (let (k, v) .. s)` over a
|
|
// `[](i64, i64)` left both binders — and every body use site of them,
|
|
// plus the N_BIN wrapping them — type_=nil: the N_FORRANGE handler
|
|
// installed the binders as SK_VAR but never back-filled their element
|
|
// type, so the N_IDENT exprtype path read a nil decl type. stamptuplebinds
|
|
// (the shared binder distributor, harec create_unpack_bindings) now peels
|
|
// the iterable element tuple and stamps each binder, so this reads 0.
|
|
package main;
|
|
|
|
export fn main() i32 = {
|
|
let buf: [2]i64;
|
|
buf[0] = 1i64;
|
|
buf[1] = 2i64;
|
|
let s: [](i64, i64);
|
|
s.ptr = buf.ptr: *(i64, i64);
|
|
s.len = 1;
|
|
s.cap = 1;
|
|
let total: i64 = 0i64;
|
|
for (let (k, v) .. s) {
|
|
total += k + v;
|
|
};
|
|
return total: i32;
|
|
};
|