I have this program:
use std::io::{self, Cursor, prelude::*};
fn file_op<R: Read>(mut reader: R) -> io::Result<()> {
// Some file operation
let mut buf = [0u8];
reader.read(&mut buf)?;
Ok(())
}
fn main() -> io::Result<()> {
let mut f = Cursor::new(vec![0xffu8]);
// Works
file_op(&mut f)?;
file_op(&mut f)?;
let x = &mut f;
// Does not work
file_op(x)?;
file_op(x)?;
Ok(())
}
I understand that the first portion (// Works
) works because any &mut T
where T: Read
also implements Read
(from impl<'a, R: Read + ?Sized> Read for &'a mut R
in libstd).
However, I don't understand why the second portion (// Does not work
) causes a use after move error. Isn't the R
type parameter a &mut Cursor
(which implements Read
) in both cases? If I'm only using references, what is getting moved? The reference variable, x
, itself?
error[E0382]: use of moved value: `x`
--> src/main.rs:21:13
|
20 | file_op(x)?;
| - value moved here
21 | file_op(x)?;
| ^ value used here after move
|
= note: move occurs because `x` has type `&mut std::io::Cursor<std::vec::Vec<u8>>`, which does not implement the `Copy` trait
Interestingly, dereferencing x
and referencing it again also works:
file_op(&mut *x)?;
file_op(&mut *x)?;