To get erased closures working across the board, I think we need to
{ function_pointer, boxed_data, refcounter_function_pointer }. Calling an erased closure is an indirect call to the function pointer with the boxed data (the unboxing happens on the callee site)That shouldn't be too hard to add to the dev backend. Fundamentally just an indirect call and some pointer data twiddling.
For the Wasm backend the call_indirect instruction requires a type signature for the called function.
It's like "call any function that takes two f32s and returns an i32".
So the IR will need to contain enough Layout info to do that. But we'll already need that just to actually pass the arguments and get the return value anyway!
There's a bit of bookkeeping too. All indirect callees have to be listed in a table in the module. But we already support this because of List.map and friends, which indirectly call Roc functions from Zig.
So I don't see any major issues.
Last updated: Nov 08 2025 at 12:13 UTC