wcc/ww: promote module-name SK_USE to value kind (use_alias), aligned to cstage
A primary-package top-level decl whose leaf also names a bundled module (`type sym` vs `import sym`; the lib/test->fnmatch->ascii -T floor's `ascii` module vs a `@test fn ascii`) collided in the flat scope: #23's installtop dup-check false-fired "duplicate fn/type" where cstage coexists. cstage keys the module name out of the value namespace by PROMOTING the same-leaf SK_USE in place to the value kind with use_alias=1 (cmd/wcc/check.c:2831/2848/2871/2907/2928/2951), so one correctly-kinded sym serves bare refs (call/structlit/var) while `name.member` still resolves the module via the `kind==SK_USE || use_alias` N_DOT guards (check.c:87/1337). This REVERSES wwstage's documented two-sym coexistence design (lib/ww/sym.ww scopelookupuselocal): keeping the SK_USE as a separate coexisting sym ripples into every bare-reference resolver (~25 scopelookup sites), and a missed site is a byte-id-consistent-but-wrong cat-A risk the gate cannot prove away — the same failure mode retired with the name-keyed variant-match cluster. The promote model is correct by construction: one sym of the right kind, identical to cstage. sym gains a use_alias field; the three N_DOT/N_CALL module-qualified guards honor use_alias. cstage installs every SK_USE in a dedicated first pass, so its value-arm promote is order-INDEPENDENT; wwstage installs in source order, so BOTH directions of the collision are promoted to reach cstage's identical single-sym end state: - use-before-value (`import aa` then `fn aa`): installtop promotes the pre-installed SK_USE to the value kind (use_alias=1). - value-before-use (`fn aa` then `import aa`): installdecl's N_USE arm promotes the pre-installed value sym in place (set use_alias=1, no coexisting SK_USE), mirroring cstage's self-import N_USE arm (check.c:2823-2834 `if (prev) prev->use_alias = 1`). Both orders compile + are cs/ww byte-identical AND byte-identical to each other. Cannot split: promote without the guards leaves `name.member` red on the promoted sym; the guards without promote are inert (no use_alias is ever set) — no bisect-clean intermediate. (#30) Pins (910/997): modfn_coexist_ok (use-before-value) AND modfn_coexist_vbu_ok (value-before-use) both accept on cstage + are cs/ww byte-id + run to exit 6 (bare fn and qualified module both resolve); the dup_fn row still rejects both stages (regression). fnmatch byte-id holds. The order-dependence is exactly what regresses silently, so both orders are pinned.
This commit is contained in:
19
test/wcc/data/modfn_coexist_ok.ww
Normal file
19
test/wcc/data/modfn_coexist_ok.ww
Normal file
@@ -0,0 +1,19 @@
|
||||
// #30 legal control — a top-level fn whose leaf matches an imported
|
||||
// MODULE name. The module bareword (SK_USE) and the value-namespace fn
|
||||
// coexist: cstage promotes the SK_USE in place with use_alias
|
||||
// (cmd/wcc/check.c:2928), wwstage keeps both as separate coexisting syms
|
||||
// (lib/ww/sym.ww scopedefineinmodule #30 cross-namespace skip). A bundled
|
||||
// `ascii` module + a primary-package `@test fn ascii` hit this in the wild
|
||||
// (989_lib_byteid via the lib/test->fnmatch->ascii -T floor). Must compile
|
||||
// clean + be cs/ww byte-identical. Mirrors a driver-emitted *.combined.ww.
|
||||
//
|
||||
// Both refs must resolve, so any mis-resolution fails to COMPILE: `aa()`
|
||||
// must bind the fn (a module is not callable), and `aa.helper()` must bind
|
||||
// through the module (the fn has no field `helper`). Accept proves both.
|
||||
package aa;
|
||||
export fn helper() i32 = { return 5; };
|
||||
|
||||
package main;
|
||||
import aa;
|
||||
fn aa() i32 = { return 1; };
|
||||
export fn main() i32 = { return aa() + aa.helper(); };
|
||||
21
test/wcc/data/modfn_coexist_vbu_ok.ww
Normal file
21
test/wcc/data/modfn_coexist_vbu_ok.ww
Normal file
@@ -0,0 +1,21 @@
|
||||
// #30 legal control — VALUE-BEFORE-USE order. The twin of
|
||||
// modfn_coexist_ok.ww with the decl order flipped: the value-namespace
|
||||
// `fn aa` is declared BEFORE `import aa`. cstage is order-independent
|
||||
// (it installs every SK_USE in a dedicated first pass, cmd/wcc/check.c
|
||||
// :2811+), so its value-arm promote always fires. wwstage installs in
|
||||
// source order, so this direction is closed by the symmetric promote in
|
||||
// installdecl's N_USE arm (set use_alias on the pre-installed value sym,
|
||||
// mirroring cmd/wcc/check.c:2823-2834). Both orders must compile clean +
|
||||
// be cs/ww byte-identical AND byte-identical to the use-before-value
|
||||
// order — the order-dependence is exactly what regresses silently.
|
||||
//
|
||||
// Both refs must resolve, so any mis-resolution fails to COMPILE: `aa()`
|
||||
// must bind the fn (a module is not callable), and `aa.helper()` must bind
|
||||
// through the module (the fn has no field `helper`). Accept proves both.
|
||||
package aa;
|
||||
export fn helper() i32 = { return 5; };
|
||||
|
||||
package main;
|
||||
fn aa() i32 = { return 1; };
|
||||
import aa;
|
||||
export fn main() i32 = { return aa() + aa.helper(); };
|
||||
Reference in New Issue
Block a user