How do I convert a Vec to a Vec without copying the vector?

You cannot change the type of a value in place in safe Rust. There is no guarantee that the two types will have the same size, alignment, or semantics.

This applies to a single value (T -> U) as well as aggregate values (Vec<T> -> Vec<U>, HashMap<K1, V1> -> HashMap<K2, V2>). Note that aggregate values are really just a special case of “single” values.

Create a new vector

The most straight-forward solution:

let buffer2 = buffer.into_iter().map(Foo).collect();

In cases where the compiler can tell that you aren’t actually changing important things, this becomes effectively a no-op:

fn convert(b: Vec<u32>) -> Vec<Foo> {
    b.into_iter().map(Foo).collect()
}

x86_64 assembly output for Rust 1.54 with optimizations:

playground::convert:
    movq    %rdi, %rax
    movq    (%rsi), %rcx
    movups  8(%rsi), %xmm0
    movq    %rcx, (%rdi)
    movups  %xmm0, 8(%rdi)
    retq

Unfortunately, this lightweight transformation isn’t currently a guaranteed property, only an implementation detail.

Use generics

You could adjust do_something_using_foo to take in a generic type and have both Foo and u32 implement a trait:

use std::borrow::{Borrow, BorrowMut};

#[derive(Debug, Clone)]
struct Foo(u32);

impl Borrow<u32> for Foo {
    fn borrow(&self) -> &u32 {
        &self.0
    }
}

impl BorrowMut<u32> for Foo {
    fn borrow_mut(&mut self) -> &mut u32 {
        &mut self.0
    }
}

fn do_something_using_foo<T>(buffer: &mut [T])
where
    T: BorrowMut<u32>,
{
}

fn main() {
    let mut buffer_u32 = vec![0u32; 100];
    let mut buffer_foo = vec![Foo(0); 100];

    do_something_using_foo(&mut buffer_u32);
    do_something_using_foo(&mut buffer_foo);
}

Unsafe Rust

It’s technically possible — you can shoot yourself in the foot as much as you’d like.

You can use something like std::mem::transmute if you know what you are doing.

However, it’s undefined behavior to use transmute with Vec as the representation of Vec is not defined. Instead, see Sven Marnach’s answer.

See also:

Leave a Comment