Type returned by clone on generic and non-generic vector

Hi,

Maybe I am a little rusty with Rust (sorry for the pun), but I cannot get why data types of the binding _cloned are differing in this two following functions:

pub fn foo_i32(list: &Vec<i32>) {
    let mut _cloned: Vec<i32> = list.clone();
}

pub fn foo_generic<T>(list: &Vec<T>) {
    let mut _cloned: &Vec<T> = list.clone();
}

Thank you

When you call a method using receiver (.) syntax, methods that take the receiver type exactly take precedence over methods that take a & or &mut version of it.

In foo_i32, list is &Vec<i32>. In deciding what function clone resolves to, Rust first asks: Is there a method named clone that accepts &Vec<i32>? Why, yes! It's <Vec<i32> as Clone>::clone, and the return type of that function is Vec<i32>, so that's what _cloned gets.

In foo_generic, list is &Vec<T>. In deciding what function clone resolves to, Rust asks: Is there a method named clone that accepts &Vec<T> (for any T)? Well, no – since T isn't known to implement Clone, we can't clone a Vec<T>. So it adds a & and tries again: Is there a method named clone that accepts &&Vec<T> (for any T)? Yes! It's <&Vec<T> as Clone>::clone, and the return type of that function is &Vec<T>, so that's what _cloned gets in this case.

(Note that if adding & fails, it tries &mut, and if &mut fails, it will add a * and start over – the compiler won't keep adding & until it finds an appropriately-named method, like it does with *.)

What are Rust's exact auto-dereferencing rules? is where I usually refer to when I get confused about autoderef.

4 Likes

Thank you!

So changing my generic implementation adding a where clause it should work then as the non-generic version:

pub fn foo_generic<T>(list: &Vec<T>) where T: Clone {
    let mut _cloned: Vec<T> = list.clone();
}
1 Like