Reputation: 103
The following minimal example does not compile:
fn main() {
let mut v = Vec::new();
foo(&mut v);
}
fn foo(v_ref: &mut Vec<u8>) {
for v in v_ref{
println!("{}", v);
}
for v in v_ref{
println!("{}", v);
}
}
The compiler suggests to modify the first for loop to this, which does compile.
for v in &mut *v_ref{
The reasoning given by the compiler is:
move occurs because
v_ref
has type&mut Vec<u8>
, which does not implement theCopy
trait
v_ref
moved due to this implicit call to.into_iter()
Question 1: Why is this necessary? It's already a reference, shouldn't the for loop give the reference back after we're done with it?
Question 2: Why does the fix work? As I understand it, the new mutable reference should invalidate the old one.
Upvotes: 0
Views: 234
Reputation: 71585
Why is this necessary? It's already a reference, shouldn't the for loop give the reference back after we're done with it?
for
loops desugar into (roughly):
{
let iterator = IntoIterator::into_iter(iter);
while let Some(v) = Iterator::next(&mut iterator) { ... }
}
Notice the IntoIterator::into_iter()
. As explained in Do mutable references have move semantics?, mutable references, as opposed to shared references, are not Copy
and thus once you move them you cannot use them anymore. Usually, the compiler inserts a reborrow, &mut *reference
that creates a new reference from the existing one and allows the existing one to still be used (after the new is no longer used), but this only happens when it is known without inference that the type is a mutable reference, and here we need inference to determine that.
Why does the fix work? As I understand it, the new mutable reference should invalidate the old one.
You can think of references as a stack; each reference created from existing one pushes an item on the stack, and when we finished using it we pop it. &mut *reference
creates a new reference, whose lifetime can be shorter than the original reference and allows the original reference to be used again after the end of the lifetime of the new reference.
Upvotes: 5