ffi M5.A.next.3b: type_eq + has_impl comptime intrinsics
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.
This commit is contained in:
1
tests/expected/168-pack-reflection-intrinsics.exit
Normal file
1
tests/expected/168-pack-reflection-intrinsics.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
8
tests/expected/168-pack-reflection-intrinsics.txt
Normal file
8
tests/expected/168-pack-reflection-intrinsics.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
s64 string bool
|
||||
true false true false
|
||||
inline-if folded: same
|
||||
Allocator/CAllocator: true
|
||||
Allocator/s64: false
|
||||
Wrap(s64)/s32: true
|
||||
Wrap(s64)/bool: false
|
||||
Wrap(bool)/s32: false
|
||||
Reference in New Issue
Block a user