Why would the borrow checker reject an inline expression but accept its broken down form?

Viewed 154

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)
}
1 Answers
Related