Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple mutable references in a loop

I'm trying to learn Rust's ownership and lifetimes in more detail, and I'm very confused by this piece of code:

let mut lst = vec![1, 2, 3];
let mut x = &mut 0;

for value in &mut lst {
    *value += 1;
    *x += 1;
    x = value;
}

*x += 1;
println!("{:?}", &lst);

From what I understand, Rust disallows having more than one mutable reference to any value, and a mutable reference to an element in a vector also borrows the vector itself. So it should not be possible to simultaneously have mutable references to two elements in a vector.

But in the code above, the body of the loop stores a mutable reference to an element in lst in x outside the loop. Then, in the next iteration, it takes another mutable reference to a different element in lst, giving me two mutable references to two elements in the list at once.

So my question is: Why is this allowed?

like image 356
Kasra Ferdowsi Avatar asked Dec 31 '25 16:12

Kasra Ferdowsi


1 Answers

While Rust does not allow you to have multiple mutable references to the same value, it does allow you to have mutable references to non-overlapping parts of the same value.

For example, you can split a &mut T into separate mutable references for each field, and the borrow checker will keep track of this for you:

struct Foo {
    x: i32,
    y: i32,
}

let mut foo = Foo { x: 0, y : 0 };

let foo_mut = &mut foo;
let x = &mut foo_mut.x;
let y = &mut foo_mut.y;

*x = 1;
*y = 2;

println!("x = {:?}", x);     // 1
println!("y = {:?}", y);     // 2
println!("foo = {:?}", foo); // Foo { x: 1, y: 2 }

Similarly, you can split a mutable slice reference &mut [T] with methods like split_at_mut and split_first_mut, which both give you two non-overlapping mutable references to the slice.

In fact, iteration of a mutable slice can be implemented using split_first_mut:

let mut lst = vec![1, 2, 3];
let mut x = &mut 0;

let mut rest = &mut *lst;
while let Some((value, rest_)) = rest.split_first_mut() {
    rest = rest_;

    *value += 1;
    *x += 1;
    x = value;
}

*x += 1;
println!("{:?}", &lst);

So it's fine for the iterator of &mut [T] (and &mut Vec<T>) to give multiple mutable references that coexist, as long as those mutable references point to different parts of the vector and do not overlap.

like image 144
Frxstrem Avatar answered Jan 02 '26 05:01

Frxstrem



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!