Explanation about an example of borrowing

Hi,

I’m trying to do the rustlings exercises to get familiar with rust, and I’m having trouble with the second execrise of move semantic.

Here is my first solution. It’s working but I don’t understand why:

// Make me compile without changing line 9! Scroll down for hints :)

pub fn main() {
    let vec0: Vec<i32> = Vec::new();
    
    // Just borrow vec0 instead of taking ownership of it
    let mut vec1 = fill_vec(&vec0);

    // This line cannot be changed
    println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);

    vec1.push(88);

    println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);

}

# Change argument type to &Vec<i32>
fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {

    let mut new_vec: Vec<i32> = Vec::new();
    
    // I thought I had to dereference vec, since its type is &Vec<i32>,
    // which reads as "reference to a Vec of i32" (if I'm not mistaken),
    // and I cannot iterate over a reference.
    //
    // for i in *vec { 
    //     new_vec.push(i);
    // }
    // 
    // But it does not work. and I don't understand why.
    // Error is "cannot move out of borrowed content"
    
    // This works though, but I just tried it randomly,
    // so not sure why. How come I have to dereference `i`?
    // Very confused here...
    for i in vec { 
        new_vec.push(*i);
    }
    
    new_vec.push(22);
    new_vec.push(44);
    new_vec.push(66);
    new_vec
}

Also, is that the correct way to copy a vector? I looked for a copy() function but did not find that.

Hope this kind of question is approriate on the forum since questions seems more general.

1 Like

Hi,

first things first, here’s another working solution (http://is.gd/Jpn8iP)

pub fn main() {
    let vec0 = Vec::new();

    let mut vec1 = fill_vec(&vec0);

    // Do not change the following line!
    println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);

    vec1.push(88);

    println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);

}

fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {
    let mut vec = vec.to_vec(); // this copies the vector for if T is `Clone`

    vec.push(22);
    vec.push(44);
    vec.push(66);

    vec
}

And a few explanations:

2 Likes

Generally, when you want to manually copy something, you call clone(). Copy is when it happens automatically without your help.

for loops are unusual.

let vec0 = vec![1, 2, 3];
// This will work perfectly because the `for` loop calls `into_iter()`
// on the vec converting it into something iterable. It is moved
// in the process so `vec` is no longer accessible.
for v in vec0 { println!("{}", v); }

let vec1 = &vec![1, 2, 3];
// This is a bit different. This calls `into_iter()` on the borrowed vector
// which does something depending on the implementation but at the
// most *cannot* modify or move the borrow. `into_iter()` on a borrowed vector
// calls `iter()` on the vec which yields borrows to each element.
for v in vec1 { println!("{}", *v); }

let vec2 = &vec![1, 2, 3];
// A `for` loop always calls `into_iter()` but sometimes the fact that
// you're working with a borrowed value may not be obvious. To make
// this more clear, you dereference first and then borrow.
for v in &*vec2 { println!("{}", *v); }

// Since a proper implementation of `into_iter()` should defer to `iter`
// and `iter_mut` in the appropriate cases, association of `iter` with `&`
// and `iter_mut` with `&mut` seems appropriate.
let mut vec3 = vec![1, 2, 3];
for v in &mut vec3 { println!("mutating {} in vec3", v); *v += 1; }
for v in &vec3 { println!("borrowing {} from vec3", v); }
for v in vec3 { println!("consumed vec3 and looking at {}", v); }
3 Likes

sorry to replying to an old topic. Since I'm also solving rustlings excersie. And This came in google search.

As per "Rust in Motion" book explanation;

  • One should avoid .copy as it will increase memory load.
  • you should instead Borrow with reference
    so in this case taking fill_vec(vec: &Vec<i32>) is correct solution. Since it also makes clear to the reader what is the purpose of this Borrow.