3

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) }
}
Community
  • 1
  • 1
Tim Bodeit
  • 9,673
  • 3
  • 27
  • 57
  • 5
    Does this answer your question? [How do I convert a Vec to a Vec without copying the vector?](https://stackoverflow.com/questions/48308759/how-do-i-convert-a-vect-to-a-vecu-without-copying-the-vector) (See especially Sven Marnach's answer, which addresses your case specifically.) – trent Nov 04 '19 at 21:18
  • 1
    *I know that it is possible to achieve a copy-free conversion by using [...] `std::mem::transmute`* —  This is [not true](https://doc.rust-lang.org/std/mem/fn.transmute.html#alternatives); it is undefined behavior to transmute a `Vec` as it is `repr(Rust)`: – Shepmaster Nov 04 '19 at 21:31
  • @trentcl: Yes, that question sufficiently matches mine. The remarks on `repr(transparent)` were especially valuable to me. – Tim Bodeit Nov 04 '19 at 22:18
  • @Shepmaster: I was aware of the fact, that doing so is "Undefined Behavior, and a bad idea". Both `convert_unsafe` and `convert_transmute` were based on the `Turning a Vec<&T> into a Vec – Tim Bodeit Nov 04 '19 at 22:28
  • 2
    @TimBodeit Great! I'd like to raise a minor clarification wrt Shepmaster's comment: `convert_transmute` is *always* UB, but `convert_unsafe` may be sound when `Asdf` is `repr(transparent)`. They are both solutions that use `unsafe`, but they are not both "equally unsafe" because one is *always* wrong whereas the other is only *sometimes* wrong. – trent Nov 04 '19 at 22:34

0 Answers0