The following code does not compile because the closure passed to map
, which borrows an argument of the enclosing function (cache
), apparently outlives the enclosing function.
use std::collections::HashMap;
fn main() {
let mut data = Vec::new();
let mut foo_cache = HashMap::new();
let foo = get_foo(7, &mut data, &mut foo_cache);
}
struct Foo<'a> {
n: &'a u8,
}
fn get_foo<'a, 'b>(n: u8,
data: &'a mut Vec<u8>,
cache: &'b mut HashMap<u8, Foo<'a>>)
-> Option<&'b Foo<'a>> {
if let Some(x) = cache.get(&n) {
Some(x)
} else {
make_foo(n, data).map(|f| {
cache.insert(n, f);
&cache[&n]
})
}
}
fn make_foo<'a>(n: u8, data: &'a mut Vec<u8>) -> Option<Foo<'a>> {
if n % 2 != 0 {
None
} else {
data.push(n);
Some(Foo { n: &data[data.len() - 1] })
}
}
Error:
error[E0373]: closure may outlive the current function, but it borrows `cache`, which is owned by the current function
--> src/main.rs:21:35
|
21 | make_foo(n, data).map(|f| {
| ^^^ may outlive borrowed value `cache`
22 | cache.insert(n, f);
| ----- `cache` is borrowed here
|
help: to force the closure to take ownership of `cache` (and any other referenced variables), use the `move` keyword, as shown:
| make_foo(n, data).map(move |f| {
I would assume that the closure would either be called immediately or not at all, and that there would be no need for it to exist after get_foo
returns. How can I tell the compiler that this is the case?