For a struct Asdf(i32);
using the default representation the memory size and alignment seem to be the same as for a raw i32
primitive.
Is there a way to cast from Vec<Asdf>
to Vec<i32>
that doesn't require any assumptions on memory equality of Asdf
and i32
? An ideal solution would be where the compiler and optimizer detect that a conversion can be made as a zero-cost cast at compile time and fall back to a copy or throw a compiler error when this is no longer the case (for example if someone were to add a second parameter to Asdf
).
Approaches tried:
Safe, copy based solution
When mapping over IntoIter
, the optimizer at opt-level = 3
does not get rid of the copy.
fn convert(from: Vec<i32>) -> Vec<Asdf> {
from.into_iter().map(|p| Asdf(p)).collect()
}
Unsafe solutions
I know that it is possible to achieve a copy-free conversion by using Vec::from_raw_parts
or std::mem::transmute
. Is there any way to do this without unsafe
code?
fn convert_unsafe(v_orig: Vec<i32>) -> Vec<Asdf> {
let mut v_orig = v_orig;
let v_from_raw = unsafe {
Vec::from_raw_parts(
v_orig.as_mut_ptr() as *mut Asdf,
v_orig.len(),
v_orig.capacity(),
)
};
std::mem::forget(v_orig);
v_from_raw
}
fn convert_transmute(v_orig: Vec<i32>) -> Vec<Asdf> {
unsafe { std::mem::transmute::<Vec<i32>, Vec<Asdf>>(v_orig) }
}