The following code does not compile, failing with `x` does not live long enough
.
use std::collections::BTreeMap;
pub fn main() {
let mut map = BTreeMap::<(i64, &i64), ()>::new();
let mut vals = vec![0];
vals.retain(|&x| {
map.get_mut(&(x, &x));
true
});
}
Playground link
It seems this is because &(i64, &i64)
cannot be borrowed as &(i64, &i64)
with a different lifetime. What might be a good workaround in this situation?
unfortunately, the standard library cannot implements Borrow
for every possible shapes of tuples. you can use a newtype wrapper as the key, something like:
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
struct Key<'b>((i64, &'b i64));
impl<'a, 'b: 'a> Borrow<(i64, &'a i64)> for Key<'b> {
fn borrow(&self) -> &(i64, &'a i64) {
&(self.0)
}
}
then simply change the type of map
to BTreeMap::<Key<'_>, ()>
should pass the borrow checker.
2 Likes
That makes sense, but it still does not compile: Rust Playground
Also, changing the get_mut
to get
makes the code compile, but the type signature for get_mut
and get
don't differ in terms of any lifetimes: Rust Playground
since Borrow
is implemented, you don't need to use Key
when calling get_mut()
, that's the whole point of Borrow
: