5

I just came across some behaviour in Rust (1.12) I cannot explain. I have a struct that implements lazy loading with a RefCell<Option<i32>> and a function to access the data:

struct Foo {
    data: RefCell<Option<i32>>
}

impl Foo {
    fn get_data(&self) -> i32 {
        if self.data.borrow().is_none() { // <--- (a)
            let d = 1337;
            self.data.borrow_mut() = Some(d); // <--- (b)
            d
        } else {
            self.data.borrow().unwrap()
        }
    }
}

This compiles but yields a runtime error: The RefCell complains that a borrow is already active when attempting to borrow_mut on line (b). The issue does not occur, however, if I change the if statement to the following:

let is_none = self.data.borrow().is_none();
if is_none {

Question: Why is the borrow in the if condition on line (a) still active inside the body of the if statement? Shouldn't the call to is_none() cause the borrow to end, since I'm only holding on to a bool afterwards, and not the borrowed value?

Fabian Schuiki
  • 1,268
  • 7
  • 18
  • 1
    Looks like it fixed in Beta and Nightly. https://play.rust-lang.org/?gist=450c131dcefde855ea0cbd832290e046&version=nightly&backtrace=0 – aSpex Nov 08 '16 at 10:01

1 Answers1

5

This is due to Rust's lexical borrowing scope.

As you have noticed, borrowing something in the condition also borrows it for the branch. This is discussed in this issue, and has since moved here.

This is a limitation that is currently fixed in the Rust 1.13 Beta and will thus probably be released in the next cycle.

Neikos
  • 1,840
  • 1
  • 22
  • 35