cstage+test: SK_USE→SK_X promotion sets use_alias
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.
This commit is contained in:
@@ -1707,7 +1707,13 @@ check_file(Checker *c, Node *file)
|
||||
Sym *prev = scope_lookup_local(c->cur, d->str);
|
||||
const char *mod = decl_mod(file, d);
|
||||
if (prev && prev->kind == SK_USE) {
|
||||
/* `use mod; ... def mod = ...;` — promote the
|
||||
* SK_USE to the def symbol but remember it was
|
||||
* also a module name so dotted qualifiers
|
||||
* (`mod.x`) keep resolving via the N_DOT path's
|
||||
* use_alias branch. Mirrors L1677. */
|
||||
prev->kind = SK_DEF; prev->type = t; prev->decl = d;
|
||||
prev->use_alias = 1;
|
||||
if (mod && prev->mod == NULL) prev->mod = mod;
|
||||
} else if (!scope_define_in_module(c->cur, d->str, mod,
|
||||
SK_DEF, t, d))
|
||||
@@ -1720,7 +1726,15 @@ check_file(Checker *c, Node *file)
|
||||
Sym *prev = scope_lookup_local(c->cur, d->str);
|
||||
const char *mod = decl_mod(file, d);
|
||||
if (prev && prev->kind == SK_USE) {
|
||||
/* `use mod; ... fn mod(...) ...;` — promote
|
||||
* but remember the module-alias so dotted
|
||||
* qualifiers (`mod.x`) keep resolving. The
|
||||
* lib/fnmatch case: `fn fnmatch(...)` shadows
|
||||
* the SK_USE leaf, and without use_alias the
|
||||
* dot-prefix path in resolve_typename loses
|
||||
* the `fnmatch.flag` lookup. */
|
||||
prev->kind = SK_FN; prev->type = t; prev->decl = d;
|
||||
prev->use_alias = 1;
|
||||
if (mod && prev->mod == NULL) prev->mod = mod;
|
||||
} else if (!scope_define_in_module(c->cur, d->str, mod,
|
||||
SK_FN, t, d))
|
||||
@@ -1734,8 +1748,12 @@ check_file(Checker *c, Node *file)
|
||||
Sym *prev = scope_lookup_local(c->cur, d->str);
|
||||
const char *mod = decl_mod(file, d);
|
||||
if (prev && prev->kind == SK_USE) {
|
||||
/* `use mod; ... let mod: T = ...;` —
|
||||
* same promote-and-alias shape as the
|
||||
* SK_DEF / SK_FN cases above. */
|
||||
prev->kind = SK_VAR; prev->type = t;
|
||||
prev->decl = d;
|
||||
prev->use_alias = 1;
|
||||
if (mod && prev->mod == NULL) prev->mod = mod;
|
||||
} else
|
||||
scope_define_in_module(c->cur, d->str,
|
||||
|
||||
Reference in New Issue
Block a user