diff --git a/test/wcc/708_param_shadow_mod.c b/test/wcc/708_param_shadow_mod.c index 57b92433..f778a496 100644 --- a/test/wcc/708_param_shadow_mod.c +++ b/test/wcc/708_param_shadow_mod.c @@ -16,12 +16,15 @@ * only for nested-scope binds whose declaring source file imports * the module. * - * row | shape | gate - * -----------+--------------------------------------+-------------- - * neg_param | `use shadowmod; fn p(shadowmod: str)`| must fail - * neg_let | `use shadowmod; ... let shadowmod` | must fail - * pos_rename | rename param away from `shadowmod` | must succeed, - * exit = 42 + * row | shape | gate + * ---------------------+--------------------------------------+-------- + * neg_param | `fn p(shadowmod: str)` | fail + * neg_let | `let shadowmod: i32 = 0;` | fail + * neg_mlet | `let (shadowmod, x) = pair();` | fail + * neg_forrange_single | `for (let shadowmod .. s)` | fail + * neg_forrange_tuple | `for (let (shadowmod, x) .. s)` | fail + * neg_mcase | `match (r) { case let shadowmod ... }` | fail + * pos_rename | rename param away from `shadowmod` | exit=42 * * Fixtures live in test/wcc/data/paramshadowmod/. Cstage-only: * wwstage's check.ww runs only inside wwdump_ww (diagnostic), and @@ -150,6 +153,10 @@ main(void) int fail = 0; fail += run_neg(cdrv, fixdir, "param"); fail += run_neg(cdrv, fixdir, "let"); + fail += run_neg(cdrv, fixdir, "mlet"); + fail += run_neg(cdrv, fixdir, "forrange_single"); + fail += run_neg(cdrv, fixdir, "forrange_tuple"); + fail += run_neg(cdrv, fixdir, "mcase"); fail += run_pos(cdrv, fixdir); fail += run_pos_selfimp(cdrv, fixdir); @@ -158,6 +165,6 @@ main(void) "param_shadow_mod: %d row(s) failed\n", fail); return 1; } - printf("param_shadow_mod: 4/4 ok\n"); + printf("param_shadow_mod: 8/8 ok\n"); return 0; } diff --git a/test/wcc/data/paramshadowmod/neg_forrange_single.ww b/test/wcc/data/paramshadowmod/neg_forrange_single.ww new file mode 100644 index 00000000..271a011e --- /dev/null +++ b/test/wcc/data/paramshadowmod/neg_forrange_single.ww @@ -0,0 +1,15 @@ +// neg_forrange_single — `for (let shadowmod .. s)` single-binding +// range loop where the loop variable shadows the imported module. +// N_FORRANGE wires check_module_shadow on the single-name branch +// (n->str), so the rule fires at the for header. + +use shadowmod; + +export fn main() i32 = { + let s: str = "abc"; + let total: i32 = 0i32; + for (let shadowmod .. s) { + total += shadowmod: i32; + }; + return total; +}; diff --git a/test/wcc/data/paramshadowmod/neg_forrange_tuple.ww b/test/wcc/data/paramshadowmod/neg_forrange_tuple.ww new file mode 100644 index 00000000..83d501bc --- /dev/null +++ b/test/wcc/data/paramshadowmod/neg_forrange_tuple.ww @@ -0,0 +1,22 @@ +// neg_forrange_tuple — `for (let (shadowmod, x) .. s)` tuple- +// destructure range loop where the first binder shadows the +// imported module. N_FORRANGE wires check_module_shadow per-name +// on the tuple branch (n->list), so the rule fires at the for +// header even though `x` is innocuous. + +use shadowmod; + +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 (shadowmod, x) .. s) { + total += shadowmod + x; + }; + return total: i32; +}; diff --git a/test/wcc/data/paramshadowmod/neg_mcase.ww b/test/wcc/data/paramshadowmod/neg_mcase.ww new file mode 100644 index 00000000..27adf820 --- /dev/null +++ b/test/wcc/data/paramshadowmod/neg_mcase.ww @@ -0,0 +1,23 @@ +// neg_mcase — `match (r) { case let shadowmod: i64 => ... }` where +// the per-arm binder shadows the imported module. N_MCASE wires +// check_module_shadow before scope_define on cs->str, so the rule +// fires at the case line. + +use shadowmod; + +fn parse(n: i64) (i64 | i32) = { + if (n < 0i64) { + return 1i32; + }; + return n; +}; + +export fn main() i32 = { + let r: (i64 | i32) = parse(42i64); + let out: i64 = 0i64; + match (r) { + case let shadowmod: i64 => out = shadowmod; + case let e: i32 => return e; + }; + return out: i32; +}; diff --git a/test/wcc/data/paramshadowmod/neg_mlet.ww b/test/wcc/data/paramshadowmod/neg_mlet.ww new file mode 100644 index 00000000..f7e50be8 --- /dev/null +++ b/test/wcc/data/paramshadowmod/neg_mlet.ww @@ -0,0 +1,15 @@ +// neg_mlet — Hare tuple destructure `let (shadowmod, x) = pair();` +// where the first binder shadows the imported module. N_MLET wires +// check_module_shadow per-binder, so the rule fires at the first +// name; the second binder `x` is innocuous. + +use shadowmod; + +fn pair() (i64, i64) = { + return 1i64, 2i64; +}; + +export fn main() i32 = { + let (shadowmod, x) = pair(); + return (shadowmod + x): i32; +};