diff --git a/selfhost/cmd/w6c/main.combined.ww b/selfhost/cmd/w6c/main.combined.ww index e39842c3..0b198370 100644 --- a/selfhost/cmd/w6c/main.combined.ww +++ b/selfhost/cmd/w6c/main.combined.ww @@ -15342,6 +15342,7 @@ use cgendecl; type aliasent = struct { aname: str, + amod: str, // originating module (`// MODULE: foo`), or empty target: *node, // the rhs type expr aanext: *aliasent, }; @@ -15354,8 +15355,9 @@ fn collectaliases(c: *cgen, file: *node) void = { let body: *node = d.lhs; if (body != nil) { if (body.kind != nkind.N_TSTRUCT) { - let a: *aliasent = amalloc(c.a, 32u64): *aliasent; + let a: *aliasent = amalloc(c.a, 64u64): *aliasent; a.aname = d.str; + a.amod = d.module; a.target = body; a.aanext = c.aliases; c.aliases = a; @@ -15373,19 +15375,27 @@ fn aliaslookup(c: *cgen, name: str) *node = { if (streq(an, name)) { return a.target; }; a = a.aanext; }; - // Module-qualified form: `pkg.alias` → try the bare leaf so a - // cross-module reference resolves the same way bare access does - // after driver concatenation. Mirrors the check.c module- - // qualified type resolution. + // Module-qualified form: `pkg.alias` → match the leaf name + // scoped to its originating module. Mirrors check.c's module- + // qualified type resolution; requiring `amod == pkg` is what + // prevents two modules with same-leaf-name aliases from + // collapsing into whichever entry appears first in the chain. let i: i32 = name.len - 1; for (i >= 0) { if (name[i] == 46u8) { // '.' + let pkg: str; + pkg.ptr = name.ptr; + pkg.len = i; let leaf: str; leaf.ptr = name.ptr + ((i + 1): u64); leaf.len = name.len - (i + 1); let b: *aliasent = c.aliases; for (b != nil) { - if (streq(b.aname, leaf)) { return b.target; }; + if (streq(b.aname, leaf)) { + if (streq(b.amod, pkg)) { + return b.target; + }; + }; b = b.aanext; }; i = -1; diff --git a/selfhost/cmd/wcc/cgen.ww b/selfhost/cmd/wcc/cgen.ww index 157875df..5733f11e 100644 --- a/selfhost/cmd/wcc/cgen.ww +++ b/selfhost/cmd/wcc/cgen.ww @@ -46,6 +46,7 @@ use cgendecl; type aliasent = struct { aname: str, + amod: str, // originating module (`// MODULE: foo`), or empty target: *node, // the rhs type expr aanext: *aliasent, }; @@ -58,8 +59,9 @@ fn collectaliases(c: *cgen, file: *node) void = { let body: *node = d.lhs; if (body != nil) { if (body.kind != nkind.N_TSTRUCT) { - let a: *aliasent = amalloc(c.a, 32u64): *aliasent; + let a: *aliasent = amalloc(c.a, 64u64): *aliasent; a.aname = d.str; + a.amod = d.module; a.target = body; a.aanext = c.aliases; c.aliases = a; @@ -77,19 +79,27 @@ fn aliaslookup(c: *cgen, name: str) *node = { if (streq(an, name)) { return a.target; }; a = a.aanext; }; - // Module-qualified form: `pkg.alias` → try the bare leaf so a - // cross-module reference resolves the same way bare access does - // after driver concatenation. Mirrors the check.c module- - // qualified type resolution. + // Module-qualified form: `pkg.alias` → match the leaf name + // scoped to its originating module. Mirrors check.c's module- + // qualified type resolution; requiring `amod == pkg` is what + // prevents two modules with same-leaf-name aliases from + // collapsing into whichever entry appears first in the chain. let i: i32 = name.len - 1; for (i >= 0) { if (name[i] == 46u8) { // '.' + let pkg: str; + pkg.ptr = name.ptr; + pkg.len = i; let leaf: str; leaf.ptr = name.ptr + ((i + 1): u64); leaf.len = name.len - (i + 1); let b: *aliasent = c.aliases; for (b != nil) { - if (streq(b.aname, leaf)) { return b.target; }; + if (streq(b.aname, leaf)) { + if (streq(b.amod, pkg)) { + return b.target; + }; + }; b = b.aanext; }; i = -1; diff --git a/selfhost/cmd/wwdump/main.combined.ww b/selfhost/cmd/wwdump/main.combined.ww index 13f44ef2..3a870aa7 100644 --- a/selfhost/cmd/wwdump/main.combined.ww +++ b/selfhost/cmd/wwdump/main.combined.ww @@ -15342,6 +15342,7 @@ use cgendecl; type aliasent = struct { aname: str, + amod: str, // originating module (`// MODULE: foo`), or empty target: *node, // the rhs type expr aanext: *aliasent, }; @@ -15354,8 +15355,9 @@ fn collectaliases(c: *cgen, file: *node) void = { let body: *node = d.lhs; if (body != nil) { if (body.kind != nkind.N_TSTRUCT) { - let a: *aliasent = amalloc(c.a, 32u64): *aliasent; + let a: *aliasent = amalloc(c.a, 64u64): *aliasent; a.aname = d.str; + a.amod = d.module; a.target = body; a.aanext = c.aliases; c.aliases = a; @@ -15373,19 +15375,27 @@ fn aliaslookup(c: *cgen, name: str) *node = { if (streq(an, name)) { return a.target; }; a = a.aanext; }; - // Module-qualified form: `pkg.alias` → try the bare leaf so a - // cross-module reference resolves the same way bare access does - // after driver concatenation. Mirrors the check.c module- - // qualified type resolution. + // Module-qualified form: `pkg.alias` → match the leaf name + // scoped to its originating module. Mirrors check.c's module- + // qualified type resolution; requiring `amod == pkg` is what + // prevents two modules with same-leaf-name aliases from + // collapsing into whichever entry appears first in the chain. let i: i32 = name.len - 1; for (i >= 0) { if (name[i] == 46u8) { // '.' + let pkg: str; + pkg.ptr = name.ptr; + pkg.len = i; let leaf: str; leaf.ptr = name.ptr + ((i + 1): u64); leaf.len = name.len - (i + 1); let b: *aliasent = c.aliases; for (b != nil) { - if (streq(b.aname, leaf)) { return b.target; }; + if (streq(b.aname, leaf)) { + if (streq(b.amod, pkg)) { + return b.target; + }; + }; b = b.aanext; }; i = -1;