Borrowed value doesn't live long enough


#1

May I add yet another borrow checker puzzle to the many threads dedicated to borrowed values that don’t live enough (I’ve read several without finding one that applied to my case.)

The following program fails to compile (full playground).

What I believe to be the bottom of my function does:

match self.cache.entry(sector) {
      ...
      Occupied(e) => Ok(e.get_mut())
                    //  ^ borrowed value does not live long enough
}

Again, I’m looking for both an explanation as well as any possible work-around.

(I’ve tried to use HashMap’s or_insert_with() method, but then I fail to be able to propagate an error to the caller.)

Thanks.


#2

into_mut. (Not sure if further explanation is needed that doc doesn’t provide.)


#3

Thanks. Wow.

I would like to understand the compiler’s reasoning for get_mut() though. What was it trying to tell me? Why did it believe the borrowed value didn’t live long enough when it syntactically appeared as though the Ok() expression was the expression returned from the function?

Also, it seems that into_mut - if I found it correctly - is unsafe. Why does this require an unsafe operation?


#4

get_mut() borrows from the entry itself but the entry dies after the match block. into_mut() moves exclusive ownership of the underlying reference to the caller, and consumes the entry, thus upholding borrow rules.


#5

As for this part, yes, I think you found the right place.

The unsafe is needed because pair() returns a *mut (K, V) and this code derefs that ptr. If I understand the surrounding code and comments correctly, the raw ptr is used for performance reasons - they represent the array of key/value entries using a raw ptr + offset calculation. This representation is used both for full (occupied) and empty (vacant) slots. The comments allude to this being more efficient than the naive alternative of a Vec<Option<(K, V)>> representation.