Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I move out of mutable self reference for Read?

I can't figure out why this code compiles:

use std::io::{Read, BufRead};

trait ReadString {
    fn read_null_terminated_string(&mut self, max_size: u64) -> std::io::Result<String>;
}

impl<R> ReadString for R
where
    R: BufRead,
{
    fn read_null_terminated_string(&mut self, max_size: u64) -> std::io::Result<String> {
        let mut buf = Vec::new();
        self.take(max_size).read_until(0, &mut buf)?;
        Ok(String::from_utf8_lossy(&buf).to_string())
    }
}

As far as I can tell BufRead is not Copy, and BufRead::take() is:

    fn take(self, limit: u64) -> Take<Self>
    where
        Self: Sized,
    {
        Take { inner: self, limit }
    }

So surely the .take() should move self, which is not allowed because I only have &mut self? I even tried with my own BufRead-like trait and I did get this error:

cannot move out of `*self` which is behind a mutable reference
move occurs because `*self` has type `R`, which does not implement the `Copy` trait

So why don't I get that error with BufRead?

like image 772
Timmmm Avatar asked Nov 23 '25 15:11

Timmmm


1 Answers

You're not invoking take() on type Self, you are invoking it on type &mut Self (the type of the self parameter) and it indeed consumes it. This works because Read has a blanket implementation impl<R: Read + ?Sized> Read for &mut R.

like image 189
Chayim Friedman Avatar answered Nov 25 '25 08:11

Chayim Friedman



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!