Files
sx/examples/closures/0315-closures-struct-field-call.sx
agra 45bd561a0d fix: resolve closure/fn-pointer struct-field call types (issue 0201)
Calling a closure or function-pointer value stored in a struct data field
(`box.run(args)`) typed the call as 'unresolved': value returns marshalled
as garbage, failable fields could not be try/catch-ed. Lowering already
dispatched these (call_closure / call_indirect); only CallResolver.plan
lacked a field-access arm. Add a closure/fn-pointer field arm to plan
(before the instance-method check, mirroring lowering's precedence — a
closure-typed field shadows a same-named method) and extend the lowering
closure-field arm to also handle bare .function fields via call_indirect.

Lock: examples/closures/0315-closures-struct-field-call.sx.
2026-06-28 09:18:30 +03:00

42 lines
1.5 KiB
Plaintext

// Calling a closure / function-pointer value stored in a STRUCT FIELD
// (`box.run(args)`) resolves the call's return type correctly — value returns
// marshal properly, and a failable field (`Closure(..) -> (T, !)`) is `try`/
// `catch`-able. The call-type resolver mirrors the lowering dispatch: a
// closure/fn-ptr field is called directly (and shadows a same-named method).
//
// Regression (issue 0201): the field-access call path typed such calls as
// `unresolved` — value returns came out as garbage, failable returns rejected
// `catch`/`try` ("operand has type 'unresolved'").
#import "modules/std.sx";
CB :: struct {
add: Closure(i64, i64) -> i64; // closure field, with args
fp: (i64) -> i64; // bare function-pointer field
work: Closure(i64) -> (i64, !); // failable closure field
}
triple :: (x: i64) -> i64 { return x * 3; }
// Field call through a `*CB` receiver inside a method, consuming the failable
// field's error channel.
run_work :: (self: *CB, n: i64) -> i64 {
v := self.work(n) catch { return -1; };
return v;
}
main :: () -> i64 {
b : CB = ---;
b.add = (x: i64, y: i64) => x + y;
b.fp = triple;
b.work = (n: i64) -> (i64, !) => {
if n < 0 { raise error.Negative; }
n * 10
};
print("{}\n", b.add(3, 4)); // 7
print("{}\n", b.fp(5)); // 15
print("{}\n", run_work(@b, 6)); // 60
print("{}\n", run_work(@b, -1)); // -1 (error path)
return 0;
}