w6c+selfhost: cross-module same-leaf type disambiguation via Sym.mod

This commit is contained in:
2026-05-15 10:26:20 +09:00
parent e349536f62
commit 66d6408cbe
15 changed files with 614 additions and 60 deletions

View File

@@ -64,18 +64,42 @@ fn seedprimitives(c: *checker) void = {
scopedefine(c.top, "append", skind.SK_FN, nil, nil);
};
// declmod — module-tag stamp for a top-level decl.
//
// The driver concatenates imported sources before the primary file and
// emits `// MODULE: foo` directives the lexer pins onto each decl's
// `module` field. We treat a decl as "imported" iff its module
// directive matches some `use IDENT;` bareword in this compilation
// unit. Primary-file decls return "" so they coexist (mod="") with
// imported decls of the same leaf name in scopelookupinmodule.
fn declmod(file: *node, d: *node) str = {
let empty: str;
if (d == nil) { return empty; };
if (d.module.len == 0) { return empty; };
if (file == nil) { return empty; };
let u: *node = file.list;
for (u != nil) {
if (u.kind == nkind.N_USE) {
if (streq(u.str, d.module)) { return d.module; };
};
u = u.next;
};
return empty;
};
// installdecl — install the top-level decl's name into the top scope.
// We don't compute its type yet (that's the resolve pass) — just bind
// the name so forward references resolve.
fn installdecl(c: *checker, d: *node) void = {
fn installdecl(c: *checker, file: *node, d: *node) void = {
if (d == nil) { return; };
let k: nkind = d.kind;
let nm: str = d.str;
let mod: str = declmod(file, d);
if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; };
if (k == nkind.N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; };
if (k == nkind.N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; };
if (k == nkind.N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; };
if (k == nkind.N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; };
if (k == nkind.N_DEF) { scopedefineinmodule(c.top, nm, mod, skind.SK_DEF, nil, d); return; };
if (k == nkind.N_TYPEDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_TYPE, nil, d); return; };
if (k == nkind.N_FNDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_FN, nil, d); return; };
if (k == nkind.N_LET) { scopedefineinmodule(c.top, nm, mod, skind.SK_VAR, nil, d); return; };
};
// resolvewalk — recursive AST walk that, for every nkind.N_IDENT and
@@ -122,8 +146,10 @@ fn resolvewalk(c: *checker, n: *node) void = {
if (nm.len > 0) {
let s: *sym = scopelookup(c.cur, nm);
// `pkg.Type` — strip the last dot prefix and look up
// the leaf if `pkg` is a use-imported name. Mirrors
// cmd/wcc/check.c resolve_typename.
// the leaf with a mod filter so same-leaf-name types
// from different imports (`bufio.stream` vs
// `io.stream`) disambiguate to the right one.
// Mirrors cmd/wcc/check.c resolve_typename.
if (s == nil) {
let dot: i32 = nm.len - 1;
for (dot >= 0) {
@@ -139,7 +165,7 @@ fn resolvewalk(c: *checker, n: *node) void = {
let leaf: str;
leaf.ptr = nm.ptr + (dot + 1): u64;
leaf.len = nm.len - (dot + 1);
s = scopelookup(c.cur, leaf);
s = scopelookupinmodule(c.cur, head, leaf);
};
};
};
@@ -927,7 +953,7 @@ export fn checkfile(c: *checker, file: *node) void = {
// Pass 1: install all top-level names.
let d: *node = file.list;
for (d != nil) {
installdecl(c, d);
installdecl(c, file, d);
d = d.next;
};