2

Consider the following example program:

struct Data {
    output: Vec<u8>,
    array: Vec<u8>
}

impl Data {
    fn peek(&self) -> u8 {
        self.array[0]
    }
    fn write(&mut self) {
        self.output.push(self.peek());
    }
}

fn main() {

}

(Ignore the naming of methods; it makes more sense in the larger scope of the actual implementation)

When I try to compile this, I get an error, that I can't borrow from self while self is mutably borrowed.

test.rs:11:26: 11:30 error: cannot borrow *self as immutable because self.output is also borrowed as mutable

I understand the concept it is addressing here; what I don't understand is how to get around this. In reality, peek does more than just read the zeroth element, and I don't want to repeat the logic of peek inside write; there must be a way for implementing this in Rust. Write and peek use completely different struct members, so there is zero chance of a race condition here.

I'm very new to Rust, so I wouldn't be surprised if I'm missing something obvious, or if there's a design pattern or best practice I'm violating. Please let me know if that's the case.

Keozon
  • 998
  • 10
  • 25

2 Answers2

3

You need to save self.peek() into a temporary

fn write(&mut self) {
    let tmp = self.peek();
    self.output.push(tmp);
}

This should work as the durations of the borrows no longer overlap.

The reason for the error is that your logic is roughly equal to:

let tmp1 = &mut self.output;
let tmp2 = self.peek();
Vec<u8>::push(tmp1, tmp2);

In this way it is more obvious why the borrows overlap.

Guvante
  • 18,775
  • 1
  • 33
  • 64
  • Thanks for the explanation. Now I feel really dumb! I can't believe I never tried splitting it! – Keozon Jan 19 '17 at 00:31
1

(I'm sure this is a duplicate but I can't seem to find one that matches exactly)

You need to split the calls out:

fn write(&mut self) {
    let byte = self.peek();
    self.output.push(byte);
}
Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138