lang: generic struct head aliases bind the template (fix 0120) — alias-follow from each author's source in head selection; loud unknown-type on the .call type tail

BoxAlias :: Box; / Box :: r.Box; now resolve instantiation, methods,
annotations, and chains through the aliased template, and re-export one
flat-import level as ordinary own decls (the facade shape the std.sx
restructure needs). selectGenericStructHead consults aliasedStructTemplate
(nominal.zig) before the global template map — own-wins/single-flat alias
author, each hop pinned to the alias author's source, ns.X RHS through
namespaceAliasVerdictFrom, depth-capped. resolveTypeCallWithBindings'
silent .unresolved tail (panicked in LLVM emission) now diagnoses
"unknown type". Also aligns the stale pre-existing calls.test.zig UFCS
plan test with the opt-in model (a47ea14). Regression: examples/0211
(+rich/+facade). Gates: zig build test 426/426, suite 587/587.
This commit is contained in:
agra
2026-06-11 18:09:01 +03:00
parent 51194a26d8
commit f2db8ecc53
13 changed files with 382 additions and 5 deletions

View File

@@ -429,14 +429,17 @@ test "plan: free-function UFCS prepends receiver, distinct from namespace_fn" {
var l = Lowering.init(&module);
const cr = CallResolver{ .l = &l };
// struct Counter, and a FREE function `bump :: (c: Counter) -> s32` — NOT
// registered as `Counter.bump`, so it can only be reached via UFCS.
// struct Counter, and a FREE ufcs function `bump :: ufcs (c: Counter) ->
// s32` — NOT registered as `Counter.bump`, so it can only be reached via
// UFCS. Dot-dispatch is OPT-IN: the fn carries `is_ufcs` and is
// registered in `fn_ast_map`, where the plan's opt-in gate reads it.
const counter = module.types.intern(.{ .@"struct" = .{ .name = module.types.internString("Counter"), .fields = &.{} } });
const c_param = ast.Param{ .name = "c", .name_span = .{ .start = 0, .end = 0 }, .type_expr = typeExpr(alloc, "Counter") };
const params = [_]ast.Param{c_param};
const ret_stmt = mk(alloc, .{ .return_stmt = .{ .value = intLit(alloc, 7) } });
const body = mk(alloc, .{ .block = .{ .stmts = &[_]*Node{ret_stmt} } });
const fd = ast.FnDecl{ .name = "bump", .params = &params, .return_type = typeExpr(alloc, "s32"), .body = body };
const fd = ast.FnDecl{ .name = "bump", .params = &params, .return_type = typeExpr(alloc, "s32"), .body = body, .is_ufcs = true };
l.program_index.fn_ast_map.put("bump", &fd) catch unreachable;
l.lowerFunction(&fd, "bump", false);
const fid = l.resolveFuncByName("bump").?;
module.functions.items[@intFromEnum(fid)].has_implicit_ctx = true;