Pack-shaped impls (`impl P(...) for Closure(..$args) -> $R`) now match concrete closure sources at xx resolution time. Concrete impls keep their priority — pack matching only fires on a concrete-key miss in `param_impl_map`. New plumbing in src/ir/lower.zig: - `PackParamImplEntry` carries the pack-shaped source TypeId plus the pack-var and ret-var names extracted from the impl AST's `target_type_expr`. `registerParamImpl` detects pack-shaped sources via `pack_start != null` on the resolved closure type and additionally registers in a new `param_impl_pack_map` keyed by `"Proto\x00<arg_mangled>"` (no source suffix). - `tryUserConversion` re-shapes the concrete lookup so the pack path runs on miss. `tryPackImplMatch` walks the pack entries, verifies the source's fixed prefix matches the impl's prefix, binds the pack-var to the source's tail param TypeIds, binds the ret-var (when the impl's return is generic) to the source return, and monomorphises the convert method. Mangled name stays keyed on the concrete source so distinct call shapes monomorphise separately. - `pack_bindings: ?StringHashMap([]const TypeId)` is saved/ restored around monomorphisation, mirroring `type_bindings`. - `resolveClosureTypeWithBindings` handles the closure_type_expr node during type resolution: when the closure carries a `pack_name` AND `pack_bindings` has a binding for it, the bound TypeIds are appended after the fixed prefix and the result is a concrete (non-pack) closure type — so the impl body's `self: Closure(..$args) -> $R` substitutes to the concrete source closure during monomorphisation. Without an active binding, the pack shape is preserved. `examples/155-pack-impl-match.sx` flips from the "no Into(Block) for cl_s32_bool__bool" lock-in diagnostic to "pack impl match ok": one user-declared `impl Into(Block) for Closure(..$args) -> $R` covers a `Closure(s32, bool) -> bool` source that stdlib has no hand-rolled impl for. Constructed Block isn't invoked (invoke=null) — the test exercises only the matching + monomorphisation, not the trampoline (step 5 of the plan). Existing concrete-impl paths unchanged: 95-objc-block-noop, 96-objc-block-multi-arg, and stdlib's hand-rolled `Into(Block) for Closure(bool) -> void` continue to pass through the concrete map first. Same-file duplicate pack impls diagnose at registration; cross-module visibility and multi-pack-impl specificity stay TODOs (matching the deferred Phase 5 work on the concrete path). 193/193 example tests + `zig build test` green.
2 lines
19 B
Plaintext
2 lines
19 B
Plaintext
pack impl match ok
|