Why Box the closure in Closure?


I’m not sure if this is a wasm_bindgen specific question or a general Rust question…

But looking at the various examples of wasm_bindgen JS Closures, e.g. here and here, it seems that the idiom is to use Closure::wrap and pass a Box instead of Closure::new

Now it does say that Closure::new is only available in nightly, so maybe it’s just to make the example code more accessible - but I’m wondering why Closure::wrap exists to begin with…

Is there a common reasoning behind this idea of wrapping a Rust closure in a Box for the sake of passing around?

On one foot - I’d think that when the Box is dropped, so is the Closure, so I’m not really clear on what’s gained by wrapping it like that (this is why I feel like it’s a fundamental Rust understanding I’m missing - not specific to wasm_bindgen, but rather the general advantage of wrapping closures, or maybe other things, in Box)



The Closure type is not Sized, indicating that different closures can have different byte lengths at runtime. This makes it impossible for the compiler to reserve enough memory for arbitrary closures anywhere on the stack. The solution is to always them on the heap (this is what Box does), and passing only the pointer around (the Box).

If you have a look at the reference of the Closure type, you can see this weird-looking accumulation of characters: impl<T: ?Sized> Closure<T>
They indicate what i said above:

T: ?Sized Allow generic type parameter to be a dynamically sized type


The Closure::wrap() function just seems to do some conversion to wasm_bindgen’s types for interfacing with JS, judging by the source of it.



Oh… interesting! does ? on a Trait carry some other meaning - or is it specific to ?Sized… (that’s the only mention of it I see on the page)



This is specific to Sized but this is a nightly feature to expand this to user defined traits.