cb was already defined, so the compiler knows the type of cb when you call it directly. When it sees the expression cb(~foo=3, ()) it only has to look at the type signature of cb and check if it’s compatible. The compiler isn’t able to do this with functions that come from arguments, though. with f => f(~foo=3, ()), the compiler has no idea what type f is until you use it. If you use it in an ambiguous way, then the compiler has to make a decision for what it should be.
Note that in either case the compiler is equally “correct.” If you have expression f(~foo=3, ()), then f could either be a function with type (~foo: int, unit) => unit or type (~foo: int=?, unit) => unit. The problem is that this ambiguity may cause the compiler to make a different decision than how you expected.
These kinds of ambiguities are rare in ReScript, though, which is probably why they seem surprising when they do appear.
Thanks for the quick response. I guess that sort of defeats the purpose of using optional arguments, since you’d have to pass ~arg=?None for arguments that you want to omit. But good to know this is a possible workaround, thanks!