yageek
yageek

Reputation: 4455

Does the documentation mention the possibility of adding the `mut` keyword in front of functions' arguments?

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?

Upvotes: 0

Views: 113

Answers (2)

Steve Klabnik
Steve Klabnik

Reputation: 15559

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.

Upvotes: 3

Tim Diekmann
Tim Diekmann

Reputation: 8476

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>.

Upvotes: 2

Related Questions