In cmd/wcc/check.c the pass-1.5 SK_USE→SK_DEF/SK_FN/SK_VAR promotion sites forgot to set prev->use_alias = 1 when the imported module's top-level decl shadowed the SK_USE leaf in flat scope. Downstream dot-prefixed lookups (resolve_typename L77, N_DOT L709) gate the module-head walk on (SK_USE || use_alias), so `mod.flag` resolution fell through to "unknown type". The SK_TYPE precedent at L1660 had the line; the three sister sites at L1709/L1722/L1736 now do too, in the same one-line shape and field-set order. The wwstage selfhost/cmd/wcc/check.ww uses coexistence rather than in-place promotion: SK_USE and same-leaf SK_TYPE/FN/DEF/VAR live as separate entries differentiated by sym.mod, and scopelookupinmodule's mod-filter already disambiguates dotted lookups — no use_alias flag needed, so the cstage bug is structurally non-reachable there. An architectural note at installdecl documents this divergence-by-design and warns against porting the flag (adding a field to `sym` changes its size and risks the wwstage cgen amalloc-undersize trap). Audit covered every SK_USE→SK_X promotion path in check.c (4 sites: SK_TYPE already-correct as precedent, SK_DEF/SK_FN/SK_VAR fixed). The surfacing case was lib/fnmatch: `fn fnmatch(...)` shadows the SK_USE leaf, so `fnmatch.flag` failed in worker-fnmatch's WIP — that test (972_fnmatch_run) now flips PASS as live integration proof. test/wcc/699_use_promote_alias.c pins all four rows with a single table-driven driver (type/fn/def/var → use mod; let m: mod.flag = mod.flag.A; return m: i32, expecting exit 42 per row). 995_self_rebuild byte-identity holds.
16 lines
612 B
Plaintext
16 lines
612 B
Plaintext
// SK_USE→SK_FN promotion (the bug). fnmod exports `fn fnmod()` and
|
|
// `type flag = enum`. Pass-1 installs SK_TYPE("flag", mod="fnmod") and
|
|
// SK_USE("fnmod") (the `fn fnmod` isn't installed in pass-1; pass-1
|
|
// only handles N_USE + N_TYPEDECL). Pass-1.5 then sees the N_FNDECL
|
|
// "fnmod", finds the SK_USE local, and promotes in place to SK_FN.
|
|
// Pre-fix that promotion forgot `use_alias = 1`, so `fnmod.flag`
|
|
// resolution failed with "unknown type fnmod.flag". Post-fix the
|
|
// build succeeds and exit code = flag.A = 42.
|
|
|
|
use fnmod;
|
|
|
|
fn main() i32 = {
|
|
let m: fnmod.flag = fnmod.flag.A;
|
|
return m: i32;
|
|
};
|