Step 3 second slice. Adds two reflection builtins used by pack-fn bodies to branch on type identity / protocol membership at compile time. type_name already existed (lower.zig:8693); reused as-is. type_eq(T1, T2) -> bool structural TypeId equality has_impl(P, T) -> bool T has a reachable impl for P Both are wired through `tryConstBoolCondition` so the inline-if ladder folds them at lower time — `inline if type_eq(...)` / `inline if has_impl(...)` collapse to a single branch with no runtime instructions, perfect for guard-based dispatch inside pack-fn bodies. `has_impl`'s protocol arg accepts two shapes: - plain protocol name: `has_impl(Allocator, CAllocator)` → walks `protocol_thunk_map["Allocator\x00CAllocator"]`. - parameterised call: `has_impl(Into(Block), s64)` → builds the param_impl_map key `"Into\x00Block\x00s64"` and checks containment. The protocol type-args resolve through `resolveTypeArg` so type aliases, generics, and pack-indexed types all work as protocol args. `computeHasImpl` is the shared implementation between the runtime builtin path and the `tryConstBoolCondition` fast path so both branches stay in sync. `examples/168-pack-reflection-intrinsics.sx` exercises every shape: - type_name for primitive types. - type_eq with both equal + unequal cases, including pointer types (s64 vs *s64). - inline-if folding type_eq. - has_impl with a real plain-protocol impl (Allocator/CAllocator → true; Allocator/s64 → false). - has_impl with a user-defined parameterised protocol (Wrap(s64)/s32 → true; mismatched target args → false). 208/208 example tests + `zig build test` green. Caveat: plain-protocol has_impl uses `protocol_thunk_map` which is lazily populated when an `xx` cast or protocol dispatch creates the thunks. For a static check before any dispatch, that could false-negative. Allocator/CAllocator works in 168 because stdlib's startup uses CAllocator through the Allocator protocol — the thunks already exist by the time has_impl runs. A more robust static check (walk fn_ast_map for "<T_name>.<method>" entries against the protocol's method list) is deferred to a follow-up if needed. LSP "undefined variable" warnings on type names in expression position (s64, *s64, Wrap(s64), etc. passed to type_eq / has_impl) are cosmetic — sema doesn't know these intrinsics accept types as args. Tracked separately.
2 lines
2 B
Plaintext
2 lines
2 B
Plaintext
0
|