I'm currently looking into doing more stuff with arrays, but I think the performance of those operations could be even better if we were allowed to somehow transmute into a Leaked<T>
the array up front, only to un-leak it when the function ends. This would let us use leak amplification without a) introducing unsafety and b) setting up a catch_panic(_)
. Is this somehow possible in Rust?
For example, creating a generic array from an iterator (this obviously does not work):
#[inline]
fn map_inner<I, S, F, T, N>(list: I, f: F) -> GenericArray<T, N>
where I: IntoIterator<Item=S>, F: Fn(&S) -> T, N: ArrayLength<T> {
unsafe {
// pre-leak the whole array, it's uninitialized anyway
let mut res : GenericArray<Leaked<T>, N> = std::mem::uninitialized();
let i = list.into_iter();
for r in res.iter_mut() {
// this could panic anytime
std::ptr::write(r, Leaked::new(f(i.next().unwrap())))
}
// transmuting un-leaks the array
std::mem::transmute::<GenericArray<Leaked<T>, N>,
GenericArray<T, N>>(res)
}
}
I should note that if we either had compile-time access to the size of T
or a type that can hide its innards from borrowck (like Leaked<T>
in the example), this is perfectly feasible.
It is possible using nodrop, but it could leak.
Let's suppose that after the first item (
a
) is consumed fromi
and written tor
, a panic happens. The remaining items fromi
would be drop, but the itema
would not. Although leaking memory is not considered unsafe, it is not desirable.I think that the approach described in the question link is the way to go. It is similar to the Vec and ArrayVec implementations. I'm using a similar approach in array library that I'm writing.