cstage+selfhost+test: refuse same-block let / param redecl (#32)
cmd/wcc/check.c silently accepted `let a; let a;` in the same block and similar redecls. Pre-#27 the localoff dedup masked it; post-#27 last-write-wins via head-first localfind. Surfaced by worker-27 during the #27 review. Cstage: 5 guard sites (check_scope_define-NULL → err) covering N_LET block-bind, N_MLET tuple binders (incl. same-tuple `let (a,a)`), N_FORRANGE tuple binders, top-level let, fn param. Voice: "<kind> '<name>' redeclared in same scope" for inner; "duplicate let %s" for top-let, matching the existing "duplicate <kind>" idiom at 1812/1851/1872. Wwstage: TODO(#11) comments at the 4 mirror sites (installdecl, N_FORRANGE, N_LET, installparams). Full enforcement waits on the checkfile pass per rob. **Unmasked by #32 (worth flagging):** selfhost/cmd/wcc/cgenexpr.ww cgcall had `let callee: *node = n.lhs;` twice at fn-body scope (copy-paste, identical value). Pre-fix silent-redecl absorbed it; post-fix the new guard rejects. Removed the second decl — outer `callee` stays visible across the intermediate block. Test 712 (redecl): 10 rows (6 neg + 4 pos), cstage-only per rob. Negative rows cover all 5 guard sites + same-tuple-dup. Positive rows pin the legal counter-shapes (cross-block, name-only bucket, forrange body, mcase-per-arm). Test 300 row 34 ("shadowing in inner scope; same scope flagged") was incorrectly asserting the bug; flipped to expect "redeclared" and added a sibling row pinning cross-block shadow stays ok. Test 709's `same_block_redecl_pin` canary (explicitly documented as flipping under #32) removed; pointer to 712 left in its place.
This commit is contained in:
@@ -96,7 +96,9 @@ static const struct row rows[] = {
|
||||
{ "fn f() void = { -true; };", "non-numeric" },
|
||||
{ "fn f() void = { *5; };", "deref non-pointer" },
|
||||
{ "fn f() void = { let x: i32 = 1; let x: i32 = 2; };",
|
||||
"ok" }, /* shadowing in inner scope; same scope flagged */
|
||||
"redeclared" }, /* same-scope let-redecl rejected (#32). */
|
||||
{ "fn f() void = { let x: i32 = 1; { let x: i32 = 2; }; };",
|
||||
"ok" }, /* nested-block shadow stays legal. */
|
||||
{ "fn f() void = { break; };", "break outside loop" },
|
||||
{ "fn f() void = { continue; };", "continue outside loop" },
|
||||
{ "fn f(x: i32) void = { x[0]; };", "indexing non-indexable" },
|
||||
|
||||
Reference in New Issue
Block a user