lang: fn aliases dispatch like their target (fix 0121) — scan-time registration through the shared alias-chain walk

Renamed fn aliases failed for EVERY kind (the filed pack-only scope was
a same-name confound: same-name re-exports already resolved through the
name-keyed fn_ast_map). scanDecls now follows ident-/ns.X-RHS const
alias chains (aliasedFnDecl; 0120's hop walk extracted as
followAliasChain) and registers the alias name in fn_ast_map
(absent-only), so every dispatch path — early pack/comptime/generic,
plain lazy-lower, plan-side typing — sees the target decl unchanged.
my_print :: s.print; / my_format :: s.format; now work (the std.sx
re-export shape). Regression: examples/0546 (+rich). Gates: zig build
test 0, suite 588/588.
This commit is contained in:
agra
2026-06-11 18:47:16 +03:00
parent f2db8ecc53
commit 721369a711
11 changed files with 264 additions and 53 deletions

View File

@@ -434,35 +434,48 @@ pub fn aliasedStructTemplate(self: *Lowering, name: []const u8, from: []const u8
}
/// One alias hop: a generic-struct author terminates the chain with its
/// rebuilt source-pinned template; an alias author recurses on its RHS —
/// bare identifier from the author's own source, `ns.X` through the
/// author's namespace edge into the target module's own member. The depth
/// cap breaks alias cycles (`A :: B; B :: A;`).
/// rebuilt source-pinned template; an alias author recurses via
/// `followAliasChain`.
fn followToTemplate(self: *Lowering, author: resolver_mod.RawAuthor, depth: u8) ?StructTemplate {
const terminal = followAliasChain(self, author, depth) orelse return null;
const sd = structDeclOfRaw(terminal.raw) orelse return null;
if (sd.type_params.len == 0) return null;
return self.buildGenericStructTemplate(sd, terminal.source);
}
/// Walk a chain of const ALIAS decls to its terminal author. Each hop
/// resolves the RHS from the hop AUTHOR's own source — a bare identifier
/// via the visible-author walk, `ns.X` through the author's namespace edge
/// into the target module's own member. A non-alias author terminates the
/// chain (callers unwrap it by domain: `structDeclOfRaw` / `fnDeclOfRaw`).
/// The depth cap breaks alias cycles (`A :: B; B :: A;`).
pub fn followAliasChain(self: *Lowering, author: resolver_mod.RawAuthor, depth: u8) ?resolver_mod.RawAuthor {
if (depth == 0) return null;
if (structDeclOfRaw(author.raw)) |sd| {
if (sd.type_params.len == 0) return null;
return self.buildGenericStructTemplate(sd, author.source);
}
const cd = constAliasOfRaw(author.raw) orelse return null;
switch (cd.value.data) {
.identifier => |id| {
const next = singleVisibleAuthor(self, id.name, author.source) orelse return null;
return followToTemplate(self, next, depth - 1);
},
.field_access => |fa| {
if (fa.object.data != .identifier) return null;
const cd = constAliasOfRaw(author.raw) orelse return author;
const next: ?resolver_mod.RawAuthor = switch (cd.value.data) {
.identifier => |id| singleVisibleAuthor(self, id.name, author.source),
.field_access => |fa| blk: {
if (fa.object.data != .identifier) break :blk null;
const target = switch (self.namespaceAliasVerdictFrom(fa.object.data.identifier.name, author.source)) {
.target => |t| t,
.none, .ambiguous => return null,
.none, .ambiguous => break :blk null,
};
var res = self.resolver();
const member_set = res.collectNamespaceAuthors(target, fa.field);
const member = member_set.own orelse return null;
return followToTemplate(self, member, depth - 1);
break :blk member_set.own;
},
else => return null,
}
else => null,
};
return followAliasChain(self, next orelse return null, depth - 1);
}
/// The fn decl a const ALIAS chain terminates at, or null when `cd` is not
/// an alias of a function. Entry for fn-alias registration (issue 0121):
/// `cd` itself seeds the chain (it IS the first alias hop), `from` is its
/// declaring source.
pub fn aliasedFnDecl(self: *Lowering, cd: *const ast.ConstDecl, from: []const u8) ?*const ast.FnDecl {
const terminal = followAliasChain(self, .{ .raw = .{ .const_decl = cd }, .source = from }, 9) orelse return null;
return Lowering.fnDeclOfRaw(terminal.raw);
}
/// The bare-VISIBLE single generic-struct author of `name` (its `StructDecl` +