0

I have a basic Reader encapsulating some generic elements:

pub struct Reader<R> {
    inner: R,
    order: Endian,
    first_ifd_offset: usize,
}

impl<R: Read + Seek> Reader<R> {
    pub fn new(reader: R) -> Result<Reader<R>> {
        let mut order_raw = [0, 0];
        reader.read_exact(&mut order_raw)?;
        let magic_number = u16::to_be(u16::from_bytes(order_raw));
        /* ... */
   }
}

This does not compile and produces the following error:

error[E0596]: cannot borrow immutable argument `reader` as mutable
  --> src/reader.rs:17:9
   |
15 |     pub fn new(reader: R) -> Result<Reader<R>> {
   |                ------ consider changing this to `mut reader`
16 |         let mut order_raw = [0, 0];
17 |         reader.read_exact(&mut order_raw)?;
   |         ^^^^^^ cannot borrow mutably

As I am getting the argument by value, the new function should be the new owner of the reader element. The compiler advises me to to add a mut keyword in front of the function argument.

Does the documentation mention the possibility of adding the mut keyword in front of functions' arguments? I was not able to find resources mentioning it.

The BufReader struct of the standard library has a similar new function and does not use a mut keyword but an unsafe block code in the body. Does unsafe prevent the usage of mut inside the function's signature?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
yageek
  • 4,115
  • 3
  • 30
  • 48

2 Answers2

3

It’s implied but not directly mentioned in the book. Both let and function arguments are patterns, so just like you can use mut in let, you can use it in arguments.

Tim Diekmann
  • 7,755
  • 11
  • 41
  • 69
Steve Klabnik
  • 14,521
  • 4
  • 58
  • 99
  • Just to confirm, in the case of `BufReader`, this is not needed due to the fact that no `&mut ref` function of the inner `Read` object is called inside the `new` function. If such a call is made later but wrapped in another `BufRead` `&mut self` function, we assume we acquired mutability for all the field the BufRead struct has acquired? – yageek Jun 27 '18 at 09:46
2

I think the compiler is very precise in saying where to add the mut. Generally the compiler tries to underline the specific places:

pub fn new(mut reader: R) -> Result<Reader<R>>

It's now possible to mutate the reader in the function. This behaves like:

pub fn new(reader: R) -> Result<Reader<R>, Error> {
    let mut reader = reader;
    // ...

As far as I know, it's only mentioned once in the book but more or less in sense of It's a pattern, you may use it in functions too.

unsafe does not fix it, it's UB:

Mutating non-mutable data — that is, data reached through a shared reference or data owned by a let binding), unless that data is contained within an UnsafeCell<U>.

Tim Diekmann
  • 7,755
  • 11
  • 41
  • 69
  • Just to confirm, in the case of `BufReader`, this is not needed due to the fact that no `mutable` function of the inner `Read` object is called inside the `new` function. If such a call is made later but wrapped in another `BufRead` `&mut self` function, we assume we acquired mutability for all the field the `BufRead` struct has acquired? – yageek Jun 27 '18 at 09:43
  • @yageek If I get your comment right, this is true, yes. – Tim Diekmann Jun 27 '18 at 09:44