How to end borrow in for-in loop

This compiles:

struct Container {
    list: Vec<String>
}

fn main() {
    let mut c = Container{ list: vec![String::from("asdf")] };
    
    let borrow = &c.list[0];   // Borrow starts here
    let copy = borrow.clone(); // Last use of borrow

    foo(&mut c);               // Can borrow again
    
    println!("{}", copy);
}

fn foo(_container: &mut Container) { }

This does not:

struct Container {
    list: Vec<String>
}

fn main() {
    let mut c = Container{ list: vec![String::from("asdf")] };
    
    for borrow in &c.list {        // Borrow starts here
        let copy = borrow.clone(); // Last use of borrow

        foo(&mut c);               // Cannot borrow again???
    
        println!("{}", copy);
    }
}

fn foo(_container: &mut Container) { }
error[E0502]: cannot borrow `c` as mutable because it is also borrowed as immutable
  --> src/main.rs:11:13
   |
8  |     for borrow in &c.list {        // Borrow starts here
   |                   -------
   |                   |
   |                   immutable borrow occurs here
   |                   immutable borrow later used here
...
11 |         foo(&mut c);               // Cannot borrow again???
   |             ^^^^^^ mutable borrow occurs here

In my mind this does the exactly same thing, doesn't it?

Do I have to manually "end" the borrow? Can I? How?

What is foo called c.list.clear()? Then the vector would be suddenly invalidated during the iteration. In this first case you're not iterating, so there's no harm in any modifications.

1 Like

This is what the for loop desugars to:

struct Container {
    list: Vec<String>
}

fn main() {
    let mut c = Container{ list: vec![String::from("asdf")] };
    
    let mut iter = (&c.list).into_iter();
    while let Some(borrow) = iter.next() {
        let copy = borrow.clone();

        foo(&mut c); // c is still borrowed by iter
    
        println!("{}", copy);
    }
}

fn foo(_container: &mut Container) { }
1 Like