This fails to compile because "r is moved", which goes against my intuition, since &mut T is Copy iirc.
What am I missing?
This fails to compile because "r is moved", which goes against my intuition, since &mut T is Copy iirc.
What am I missing?
&mut T
isn't Copy
, because that would result in multiple exclusive references to the same T
. You can reborrow it, though. This fixes the problem:
fn act<T: Read + Seek>(r: &mut T)
{
{
let mut a = Reader::new(&mut *r);
a.read().unwrap();
}
{
let mut b = Reader::new(r);
b.read();
}
}
Mutable references are not Copy. If they were, you could trivially construct multiple mutable references to the same backing object.
Oh, I see.
So why does this compile?
The type is changed, but the use of r
is the same
The two lifetimes don't overlap, that is why. If you actually try to use a
after constructing b
, it fails to compile, as expected.
The reason is a bit technical and IMO arbitrary. Basically whenever rust’s type checker can easily and early on figure out that a function takes a mutable reference as an argument, then it will implicitly introduce a re-borrow instead of moving the mutable reference. Similar behavior can be seen when you assign variables. E.g.
let mut x = 42;
let y = &mut x;
let z = y;
dbg!(y);
won’t work, but
let mut x = 42;
let y = &mut x;
let z: &mut i32 = y;
dbg!(y);
or
let mut x = 42;
let y = &mut x;
let z: &mut _ = y;
dbg!(y);
will, because the type checker sees early on that the variable z
is a mutable reference, so the assigned value y
will be re-borrowed, basically turning the code into the equivalent
let mut x = 42;
let y = &mut x;
let z: &mut _ = &mut *y;
dbg!(y);
In your code example the difference is between a function generically expecting any type T
or any mutable reference type &mut T
, in the latter case the compiler will introduce the re-borrow for you. It’s a bit stupid/arbitrary of course, since the compiler does eventually figure out that it’s dealing with mutable references in both cases.
I personally think that we should try to change rustc in the future so that all of the above compiles. Such a change should also make your original code compile.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.