I would naively expect the two function try_drain_*
below to have the same behavior, yet the first fails to compile while the second is executed without issue.
struct Container {
map: RefCell<HashMap<i32, i32>>,
}
impl Container {
fn try_drain_inline(&self) {
self.map.borrow_mut().drain();
}
fn try_drain_broken_down(&self) {
let mut guard = self.map.borrow_mut();
guard.drain();
}
}
The borrow checker complains about try_drain_inline
on the playground:
error[E0597]: borrowed value does not live long enough --> src/main.rs:15:5 | 14 | self.map.borrow_mut().drain(); | --------------------- ^ temporary value dropped here while still borrowed | | | temporary value created here | = note: values in a scope are dropped in the opposite order they are created
whereas it is fine with try_drain_broken_down
.
It seems that there is an issue with the order in which the temporaries it created are destroyed; and "manually" materializing the temporaries rectifies the situation...
Why would the borrow checker reject the inline form and accept the broken down one?
Note: my real code is a try_pop
function which requires TWO intermediate variables:
fn try_pop(&self) -> Option<i32> {
let mut guard = self.map.borrow_mut();
let mut drain = guard.drain();
drain.next().map(|(_, t)| t)
}