feat: pointee($P: Type) -> Type comptime reflection builtin

Project a pointer type to its target: `pointee(*X)` -> `X`. The one reflection
primitive missing for the `race` result synthesis (`*Task(A)` -> `A` via
`field_type(pointee(*Task(A)), 0)`) — reflection could read aggregate fields but
was blind to a pointer's target type.

Mirrors the `field_type` builtin: declared `#builtin` in std/core.sx, resolved as
a lower-time type-call fold in resolveTypeCallWithBindings (src/ir/lower/generic.zig)
so it composes in any type-arg slot. `.pointer` -> pointee, `.many_pointer` ->
element; a non-pointer arg is a loud diagnostic + `.unresolved` sentinel (no silent
fallback). Adversarially reviewed (SHIP). Locked by
examples/comptime/0647-comptime-pointee-reflection.sx. Suite green (819/0).

PLAN-RACE step 1 of 6.
This commit is contained in:
agra
2026-06-26 12:47:02 +03:00
parent dea96bd66a
commit f1d298764f
6 changed files with 57 additions and 0 deletions

View File

@@ -38,6 +38,10 @@ type_of :: (val: $T) -> Type #builtin;
type_name :: ($T: Type) -> string #builtin;
field_count :: ($T: Type) -> i64 #builtin;
field_name :: ($T: Type, idx: i64) -> string #builtin;
// The target type of a pointer: `pointee(*X)` -> `X`. Comptime reflection,
// folded at lower time like `field_type` (so it composes in any type-arg slot).
// A non-pointer argument is a loud compile error, not a silent fallthrough.
pointee :: ($P: Type) -> Type #builtin;
field_value :: (s: $T, idx: i64) -> Any #builtin;
is_flags :: ($T: Type) -> bool #builtin;
type_is_unsigned :: ($T: Type) -> bool #builtin;