2

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
bearbear2k
  • 56
  • 6
  • i think, taking ownership or using FnOnce and taking ownership of self are the only ways – Swift - Friday Pie May 24 '17 at 15:28
  • If you are interested in solving the problem instead of answering the question, [here is one possible way](https://play.integer32.com/?gist=84e4aa3068c4b50c3f5c88c36f7e8a40) as described in [How to lookup from and insert into a HashMap efficiently?](https://stackoverflow.com/q/28512394/155423). – Shepmaster May 28 '17 at 17:04

0 Answers0