Files
sx/examples/160-pack-hetero-ret.sx
agra 2e0b97aaa5 ffi M5.A.next.2b.fu2.C: heterogeneous pack ret + OOB diagnostic
Two follow-on fixes for follow-up #2 (generic pack-fn return).

(1) `pack_arg_types` — a new type-only pack binding consulted by
`inferExprType` for `<pack_name>[<int_literal>]`. The earlier
`pack_arg_nodes`-via-synthesized-idents path lost the type
during return-type inference because the synthesized idents
("__pack_args_0" etc.) only resolve once the mono scope is set
up — but the inference runs BEFORE scope setup. Now
`monomorphizePackFn` installs `pack_arg_types[<pack>] =
arg_types` alongside the existing nodes/count maps, and
`inferExprType` consults it directly.

`foo(..$args) -> $R => args[2]` called as `foo(42, 3.2, "hello")`
now correctly returns "hello" (string) — the third element-
typed pick threads through inference to the mono ret_ty.

(2) `diagPackIndexOOB` — focused diagnostic for `args[<lit>]`
where the literal exceeds the pack arity. Pre-fix the
substitution returned null and the standard slice-indexing
fall-through emitted "unresolved args" — burying the real
cause. Now: "pack index 2 out of bounds: 'args' has 1
element" at the index span.

Tests:
- `examples/160-pack-hetero-ret.sx` — generic `$R` with non-
  zeroth heterogeneous pick (returns "hello").
- `examples/161-pack-index-oob.sx` — call passes 1 arg but
  body indexes args[2]; locks in the OOB diagnostic shape.

200/200 example tests + `zig build test` green.
2026-05-27 16:34:26 +03:00

26 lines
840 B
Plaintext

// Variadic heterogeneous type packs — generic `$R` with
// heterogeneous element pick. `foo(..$args) -> $R => args[2]`
// returns the THIRD arg's value; the ret type is inferred from
// the third arg's concrete type per call shape.
//
// foo(42, 3.2, "hello") → returns "hello" (string).
//
// Exercises:
// - generic `$R` inference for non-zeroth pack indices.
// - heterogeneous mixed-type call args binding into distinct
// types per position (s64, f64, string).
// - `pack_arg_types` type-only binding for `inferExprType`
// pre-mono-scope: without it, the synthesized-ident detour
// loses the type because the scope isn't set up yet during
// return-type inference.
#import "modules/std.sx";
foo :: (..$args) -> $R => args[2];
main :: () -> s32 {
a := foo(42, 3.2, "hello");
print("{}\n", a);
return 0;
}