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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With