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?
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.
In the end you do not hold a mut reference more than once,in x = value
the reference is moved into x
. It would be different if that line was first in the loop:
fn main() {
let mut lst = vec![1, 2, 3];
let mut x = &mut 0;
for value in &mut lst {
x = value;
*value += 1;
*x += 1;
}
*x += 1;
println!("{:?}", &lst);
}
In where of course the compiler complains:
error[E0503]: cannot use `*value` because it was mutably borrowed
--> src/main.rs:8:9
|
6 | x = value;
| ----- borrow of `*value` occurs here
7 |
8 | *value += 1;
| ^^^^^^^^^^^ use of borrowed `*value`
9 | *x += 1;
| ------- borrow later used here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.