1

I want to make a closure hold &mut Vec, but these simple few lines of code can't compile.

I know this can be solved with RefCell, I just can't figure the error out.

struct Server<'a> {
    data: &'a mut Vec<i32>,
}

fn main() {
    let mut data = vec![1, 2, 3];
    let mut c = || {
         Server{
            data: &mut data,
        }
    };
    let server = c();
}

Rust playground link

The error message is:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> src/main.rs:36:19
   |
36 |             data: &mut data,
   |                   ^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 34:17...
  --> src/main.rs:34:17
   |
34 |     let mut c = || {
   |                 ^^
note: ...so that closure can access `data`
  --> src/main.rs:36:19
   |
36 |             data: &mut data,
   |                   ^^^^^^^^^
note: but, the lifetime must be valid for the call at 39:18...
  --> src/main.rs:39:18
   |
39 |     let server = c();
   |                  ^^^
note: ...so type `Server<'_>` of expression is valid during the expression
  --> src/main.rs:39:18
   |
39 |     let server = c();
   |                  ^^^

error: aborting due to previous error

Update:

I found this post answered the question, but I could not understand some parts of it:

It turns out that, returning &'a mut i32 is not feasible for the shorter-live invocation of call_mut. What we’ve really wanted for the return type of call_mut, was something like:

impl<'a> FnMut<(usize,)> for Closure<'a> {
    extern "rust-call"
    fn<'b> call_mut(&'b mut self, (i,): (usize, )) -> &'b mut i32 {
        self.inner.get_mut(i).unwrap()
    }
}
  1. Why the call_mut fn has to use a 'b lifetime instead of 'a?
  2. I found the code would work if change data: &mut Vec<i32> to data: &Vec<i32>, which makes me more confused that why lifetime is related to mut?
Simson
  • 3,373
  • 2
  • 24
  • 38
mingxin
  • 391
  • 3
  • 7
  • 1. is answered by [How do I return a reference to something inside a RefCell without breaking encapsulation?](https://stackoverflow.com/q/29401626/3650362) (the answers suggest ways to fix it); 2. is related to [Why does linking lifetimes matter only with mutable references?](https://stackoverflow.com/q/32165917/3650362), but I'm not sure exactly why the compiler doesn't like this. I tried making it a `move` closure and taking the reference outside the closure to no effect, which makes me think I might be missing the point. – trent Sep 29 '19 at 13:54
  • This question was [cross-posted to users.rust-lang.org](https://users.rust-lang.org/t/why-this-rust-fnmut-closure-code-has-lifetime-errors/33063). – trent Sep 29 '19 at 14:03
  • Does this answer your question? [Why can I not return a mutable reference to an outer variable from a closure?](https://stackoverflow.com/questions/52752259/why-can-i-not-return-a-mutable-reference-to-an-outer-variable-from-a-closure) – kmdreko Feb 23 '21 at 20:08

0 Answers0