Files
sx/examples/0214-generics-ufcs-closure-return-pack.sx
agra 362674f04d issue 0151 RESOLVED: infer generic $T through generic-struct / pointer / UFCS-pack params
The generic-inference engine could not bind a $T from a generic-struct
argument head. Four gaps, all on the inference + UFCS dispatch path:

- extractTypeParam / matchTypeParam(Static) gained a parameterized_type_expr
  arm: recover the arg instance's recorded per-param bindings
  (struct_instance_bindings + the template's ordered type_params via
  struct_instance_author) and recurse positionally, so $T binds from
  Box($T) <=> Box(i64) like it does from []$T <=> []i64. This also fixes
  the pointer case — *Box($T) recurses into its Box($T) pointee.
- The pointer_type_expr arm now falls through to match the pointee against a
  non-pointer arg (auto-address-of: a *Box($T) param accepts a by-value
  Box($T), e.g. the UFCS receiver b.m()).
- ExprTyper.inferType gained a .lambda arm building the closure type from the
  lambda's annotations, so the UFCS binder (which types args from the raw AST
  before they are lowered) can bind a Closure(..) -> $R from the worker's
  declared return type.
- A pack UFCS target (worker: Closure(..) -> $R, ..$args) now routes through
  the same lowerPackFnCall the direct call uses, with the receiver spliced in
  as args[0] (lowerPackFnCall reads only call_node.args, never the callee).

Regression tests: examples/0214 (direct + UFCS closure-return pack) and
examples/0215 (by-value / pointer / multi-param / nested / UFCS-auto-ref
generic-struct-head inference). Suite green 728/0.
2026-06-21 05:25:39 +03:00

27 lines
1003 B
Plaintext

// Generic inference where `$R` comes from a worker closure's RETURN type
// through a variadic `..$args` pack — both the DIRECT spelling
// `mymk(bx, worker, 40, 2)` and the UFCS dot-call `bx.mymk(worker, 40, 2)`
// resolve `$R = i64` identically and build `Wrap($R)` correctly.
// Regression (issue 0151): the UFCS path used to splice the receiver as
// arg 0 without running the direct path's pack/closure-return binding, so
// `$R` stayed `.unresolved` and SIGTRAPped at LLVM emission.
#import "modules/std.sx";
Box :: struct { n: i64; }
Wrap :: struct ($R: Type) { value: R; }
mymk :: ufcs (b: Box, worker: Closure(..$args) -> $R, ..$args) -> Wrap($R) {
f : Wrap($R) = ---;
f.value = worker(..args);
return f;
}
main :: () -> i32 {
bx : Box = .{ n = 1 };
direct := mymk(bx, (a: i64, b: i64) -> i64 => a + b, 40, 2);
ufcs := bx.mymk((a: i64, b: i64) -> i64 => a + b, 40, 2);
print("direct={}\n", direct.value);
print("ufcs={}\n", ufcs.value);
return 0;
}