0

Is there a good pattern for dealing with this situation?

struct Thing {
    x: i32,
}

impl Thing {
    fn write_and_get_val(&mut self) -> i32 {
        self.x = 5;
        self.x
    }

    fn read_only(&self, val: i32) {
        println!("x is {}, val is {}", self.x, val);
    }
}

fn main() {
    let mut t = Thing { x: 0 };

    t.read_only(t.write_and_get_val());
}
error[E0502]: cannot borrow `t` as mutable because it is also borrowed as immutable
  --> src/main.rs:20:17
   |
20 |     t.read_only(t.write_and_get_val());
   |     -           ^                    - immutable borrow ends here
   |     |           |
   |     |           mutable borrow occurs here
   |     immutable borrow occurs here

If I make a temporary variable out of the result of write_and_get_val, it's fine which is obviously a relatively easy fix, it's just a bit tedious. I guess because read_only borrows immutably before the nested call gets made, it doesn't work.

The above is a contrived example. My actual use case is for a parser, where I"m writing something like:

self.expecting(self.parse_string("Carrots McDougal"), "a good pony name")?;

parse_string mutates the parser by moving it forward in the source string, and expecting only needs to read from it in order to print out the portion of the source text that was seen instead of expected.

Ideally I wouldn't have to make temporary variables each time I do this.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Joseph Humfrey
  • 2,974
  • 2
  • 23
  • 34
  • The duplicate applied to this question: `let val = t.write_and_get_val();` and only then `t.read_only(val);` – E_net4 Sep 26 '18 at 14:58
  • For what it's worth, the code in this question doesn't compile with non-lexical lifetimes enabled, while the code in the duplicate _does_ compile. The main difference seems to be that the inner function call incurs the mutable borrow and the outer call the immutable borrow, while it's the other way around in the duplicate. I don't fully why the code in this question doesn't compile with NLLs. – Sven Marnach Sep 26 '18 at 15:07
  • Good point! Here's a playground demonstrating it not working with NLLs: https://play.rust-lang.org/?gist=6ce6410796d70241c9baaab0e740051d&version=nightly&mode=debug&edition=2015 – Joseph Humfrey Sep 26 '18 at 16:45

0 Answers0