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.
26 lines
799 B
Plaintext
26 lines
799 B
Plaintext
// 901_massign_blank — tuple multi-assign discard `_` gap fixture for the
|
|
// 901 asserttyped net (class G). In `_, a = f()` the blank `_` parses to
|
|
// an empty-str N_IDENT with no decl, so the generic N_IDENT exprtype path
|
|
// left it type_=nil (945's own comment documents the gap). The `_` is a
|
|
// GAP, not an exemption — the slot has a real element type ([]u8 here), so
|
|
// stamptuplebinds(define=false) stamps it with that element type (harec
|
|
// drops `_` but still advances the tuple slot). a is pre-declared and
|
|
// resolves the normal way; this reads 0.
|
|
package main;
|
|
|
|
fn mk() ([]u8, i64) = {
|
|
let b: str = "hi";
|
|
let p: []u8;
|
|
p.ptr = b.ptr;
|
|
p.len = 2;
|
|
p.cap = 5;
|
|
return (p, 7i64);
|
|
};
|
|
|
|
export fn main() i32 = {
|
|
let a: i64 = 0i64;
|
|
_, a = mk();
|
|
if (a != 7) { return 1; };
|
|
return 0;
|
|
};
|