Question about generics, i32 and moving out of borrowed context


#1

Hi,

I am currently learning Rust and playing with vectors. For fun I wanted to write a function that turns a slice into a vector.

Here is one that is working:

pub fn to_vec_from_slice_with_clone<T: Clone>(s: &[T]) -> Vec<T> {
    let mut v: Vec<T> = Vec::with_capacity(s.len());
    for i in s.iter() {
        let j = i.clone();
        v.push(j);
    }
    v
}

This one does not work:

pub fn to_vec_from_slice<T>(s: &[T]) -> Vec<T> {
    let mut v: Vec<T> = Vec::with_capacity(s.len());
    for i in s.iter() {
        v.push(*i);
    }
    v
}

Compiler says:
error: cannot move out of borrowed content
src/vecutils.rs:18 v.push(*i);

Makes sense to me.

But why does this work?

pub fn to_vec_from_int_slice(s: &[i32]) -> Vec<i32> {
    let mut v: Vec<i32> = Vec::with_capacity(s.len());
    for i in s.iter() {
        v.push(*i);
    }
    v
}

Same function but i32 instead of T.
It compiles and a test showed that it is working.

What is the difference here? Why does T only work with cloning but i32 right away?

Markus


#2

i32 implements Copy and can be implicitely and trivially copied just by copiing the memory.

With T: Copy the second version should work, although the first one is better because it can clone even non-trivial types like String.


#3

Ok, when i32 is implicitly copied it makes sense.
Is there a list of data types that are implicitly copied?

Markus


#4

Yes: http://doc.rust-lang.org/1.0.0-alpha/std/marker/trait.Copy.html


#5

additionally the primitive types, basically all integers, floats and I think raw pointers implement copy


#6

Thanks! Very helpful.


#7

and shared references and slices (neither when mutable).