core::mem::MaybeUninit allows many useful patterns related to delayed and/or partial initialization. However, currently its safe subset of API doesn't play well with APIs like that of wasm_bindgen_futures::spawn_local
and core::pin::Pin.
Assume that we have an Rc<MaybeUninit<T>>
and we would like to initialize it using wasm_bindgen_futures::spawn_local
. At the time of writing, we already can do that, yet we'd need to core::mem::transmute
the clone of Rc<MaybeUninit<T>>
to Rc<T>
after initialization. However, what we really want to do is to provide a guarantee that the closure initializes the Rc<MaybeUninit<T>>
and have a built-in safe mechanism to "properly initialize" the data.
The way I understand it, this idea of proper initialization is similar to core::marker::Send
and core::marker::Sync
. That is, a structure is properly initialized if all of its fields are properly initialized. Interaction with core::marker::PhantomData
has to be explored but you can get the idea.
Then we can have init
arguments/parameters.
fn initialize(init n: MaybeUninit<u32>) {
n.write(42);
}
fn main() {
let n = MaybeUninit::<u32>::uninit();
initialize(init n);
// we assert that the type of `n` is `u32`
let _ = core::convert::identity::<u32>(n);
}
As a bonus, init
arguments/parameters would work even with core::pin::Pin
!
We can have init
work with types:
struct PartiallyInitialized {
a: u32,
b: Rc<MaybeUninit<u32>>,
}
// struct FullyInitialized {
// a: u32,
// b: Rc<u32>,
// }
type FullyInitialized = init PartiallyInitialized;
This is not enough to make init
version of wasm_bindgen_futures::spawn_local
because we would need Fn*
traits aware of init
and async
effects. However, it would bring us a leap closer to that.
Since init
is a popular identifier, perhaps it would be wise to make it a positional keyword.
This feature is similar to the unstable placement new feature that was removed from Rust a while back.