# 0121 — aliasing a comptime-pack fn (`..$args`): "unresolved ''" > **RESOLVED** (2026-06-11, same session — Agra-directed). The symptom > was broader than filed: RENAMED fn aliases failed for EVERY fn kind > (plain `helper2 :: r.helper;` too) — the "plain fns verified working" > claim below was a same-name confound (same-name re-exports resolve > through the name-keyed global `fn_ast_map`, no alias mechanism > involved; `my_pack :: r.my_pack;` already worked for packs too). > Fix: fn aliases register at SCAN time — `scanDecls`' const-decl arm > follows ident-/`ns.X`-RHS alias chains via `aliasedFnDecl` > (nominal.zig; shares 0120's hop walk, now extracted as > `followAliasChain`) and, when the chain terminates at a fn decl, > registers the ALIAS name in `fn_ast_map` (absent-only — a real > same-name fn keeps its slot). Every dispatch path reads that map > (early pack/comptime/generic, plain lazy-lower, plan-side typing), > so the alias dispatches exactly like the target with no per-path > changes. Verified matrix: same-file pack alias (the repro), renamed > plain / generic / pack through a facade, and `my_print :: s.print;` > / `my_format :: s.format;` over std's real pack fns. Regression: > `examples/0546-packs-fn-alias.sx` (+ `-rich.sx` companion). Gates: > zig build test 0, suite 588/588. ## Symptom A const alias of a function whose signature carries a comptime pack (`..$args`) is not callable — every call through the alias fails with `unresolved ''`. All three alias shapes fail identically: - same-file bare: `sum_alias :: pack_sum;` → `unresolved 'sum_alias'` - bare RHS over a flat import: `my_print :: print;` (std's `print`) → `unresolved 'my_print'` - namespace RHS: `my_print :: s.print;` with `s :: #import "modules/std.sx";` → `unresolved 'my_print'` Contrast (all verified working): plain concrete fns (`helper :: r.helper;`), runtime-generic fns (`first_of :: r.first_of;` with `(xs: []$T) -> T`), and — since 0120 — generic struct heads (`List :: list.List;`). Only the comptime-pack shape misses. Expected: the alias dispatches exactly like the target — `my_print("x {}\n", 1)` behaves as `print("x {}\n", 1)`. (If fn aliasing of pack fns is NOT meant to be promised, the hypothesis is wrong and the decl or the call should get a clean tailored diagnostic instead — but the std.sx-as-pure-re-exports restructure wants `print :: fmt.print;` to work, so support is the desirable outcome. Confirm with Agra only if support turns out prohibitively deep.) ## Reproduction ```sx #import "modules/std.sx"; pack_sum :: (..$args) -> i64 { args[0] + args[1] } sum_alias :: pack_sum; main :: () { print("{}\n", sum_alias(3, 4)); // error: unresolved 'sum_alias' } ``` Direct `pack_sum(3, 4)` works; only the aliased spelling fails. ## Investigation prompt Comptime-pack calls (`..$args` — NOT slice-variadics `..xs: []T`) dispatch EARLY in call lowering, keyed on the callee NAME against the pack-fn template registry (the `fn_ast_map` entry whose FnDecl has a comptime pack param; the early-dispatch gate lives in the call path — `src/ir/lower/call.zig` / `src/ir/packs.zig`, grep for the pack-param detection on the callee). An alias name has no `fn_ast_map` entry, so the early pack dispatch misses; no later stage handles pack fns (they cannot lower as ordinary declared functions — each call site expands with its own bound pack), so the call falls through to the generic `unresolved ''`. The fix likely: where the early pack dispatch resolves the callee name, on a miss follow const-ALIAS decls to their target FnDecl and dispatch with the TARGET's fd under the alias's call node. Issue 0120's fix added exactly this follow for generic STRUCT heads — `aliasedStructTemplate` in `src/ir/lower/nominal.zig` (`singleVisibleAuthor` + hop-by-hop `followToTemplate`, each hop resolved from the ALIAS AUTHOR's source, `namespaceAliasVerdictFrom` for `ns.X` RHS, depth-capped). Mirror that shape for fn targets — a `followToFnDecl` sibling reusing `singleVisibleAuthor` (consider extracting the shared walk) — and route the early pack dispatch through it. Mind: own-wins / single-flat collision semantics must match 0120's (≥2 flat alias authors → loud, no silent pick), and the ufcs-alias map (`name :: ufcs target;`) is a DIFFERENT mechanism (`ufcs_alias_map`) — don't conflate. Verification: 1. The repro prints `7`, exit 0. 2. Matrix: same-file bare alias, bare RHS over a flat import (`my_print :: print;`), namespace RHS (`my_print :: s.print;` / `my_format :: s.format;` — formats AND returns a value), and a consumer one flat hop from the aliasing facade. 3. Plain-fn and generic-fn aliases unchanged (examples 0211 family). 4. `bash tests/run_examples.sh` — 587/587 baseline must hold; pin the repro as a regression example per CLAUDE.md. Context: BLOCKS the std.sx-as-pure-re-exports restructure — `print` / `format` are the prelude's most-used names and are exactly this shape (`($fmt: string, ..$args)`). Generic struct heads (`List`) were unblocked by 0120; this is the remaining known gap. Still unprobed for the restructure (next session, after this fix): protocol aliases (`Allocator`, parameterized `Into`), `#builtin` decl aliases (`size_of`, `out`, `string :: []u8`), `extern` decl aliases (`memcpy`).