I was trying to initialize an array using a user provided callback function. So I figured I would use mem::unitialized to do (The Rustonomicon suggests that this is allowed, as it provided example of that function with arrays). This function works... sorta.
use std::mem;
use std::ptr;
fn init_array<T, F: Fn() -> T>(f: F) -> [T; 20] {
unsafe {
let mut arr: [T; 20] = mem::uninitialized();
for item in &mut arr {
ptr::write(item, f());
}
arr
}
}
However, there is a possibility of panic occuring, as a function is provided by a quite panicky programmer. If that were to happen, and T would have a Drop implementation, then Drop would be called on uninitialized value, and it would likely lead to undefined behaviour, which as most C programmers will tell you is worst thing ever.
So an array could be wrapped in a type that has a Drop implementation whose purpose is to only drop elements that were assigned (while also storing array length). However, currently Rust appear doesn't provide a way to stop implicit drop calls for each structure element after calling drop function.
The Rustonomicon suggests to use an Option type as a workaround to make sure array value is None after leaving drop function. However, this doesn't exactly work. With null pointer optimization (caused in a type like Option<[&i32; 20]>), Option type tag is not written in output assembly, as Rust trusts the type to have a non-zero value (which normally would be the case).
Can somebody suggest me either how to do it with unsafe code, or better yet, a module that does so or a way to do it in a safe code without doing allocations (so storing values in Vec<T>, and then moving them is not an option).