4

I want to create a closure which closes upon a mutable reference to something, and then returns mutable references with created from the original one.

I've minimized my code to this function (playground):

fn produce_closure<'a>(string: &'a mut String) -> impl FnMut() -> &'a mut String + 'a {
    move || &mut *string
}

When I try to compile the above code, I get this error:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
 --> src/lib.rs:2:13
  |
2 |     move || &mut *string
  |             ^^^^^^^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 2:5...
 --> src/lib.rs:2:5
  |
2 |     move || &mut *string
  |     ^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
 --> src/lib.rs:2:13
  |
2 |     move || &mut *string
  |             ^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 1:20...
 --> src/lib.rs:1:20
  |
1 | fn produce_closure<'a>(string: &'a mut String) -> impl FnMut() -> &'a mut String + 'a {
  |                    ^^
note: ...so that reference does not outlive borrowed content
 --> src/lib.rs:2:13
  |
2 |     move || &mut *string
  |             ^^^^^^^^^^^^

In order to figure out if this kind of a closure was possible, I tried writing it by hand (playground):

struct HandClosure<'a>(&'a mut String);

impl<'a> HandClosure<'a> {
    fn produce(capture: &'a mut String) -> Self {
        Self(capture)
    }

    fn call_mut(&'a mut self) -> &'a mut String {
        self.0
    }

    fn call_once(self) -> &'a mut String {
        self.0
    }
}

And that code compiles fine. Is this a compiler bug? What am I missing?

timotree
  • 1,325
  • 9
  • 29
  • Hi there! I think your question is answered by my answer [here](https://stackoverflow.com/q/52752259/2408867). The reasons for why this doesn't work are subtle, so please take your time to understand the answer I linked. I hope this helps! Please let us know if the linked answer indeed answers your question. Thanks! – Lukas Kalbertodt Sep 01 '19 at 18:33
  • 1
    In particular, regarding your `HandClosure` code: you use `fn call_mut(&'a mut self)`, but that's not the same signature as in `FnMut`. There, it's `fn call_mut(&mut self, ...)` meaning that the `self` object gets a new, anonymous lifetime and not the same lifetime as the reference the closure is storing. This lifetime difference is why your small example compiles. Remove the `'a` and you will get an error as well. – Lukas Kalbertodt Sep 01 '19 at 18:36
  • We've closed this as dupe now. If you disagree that the linked answer answers your question, let us know. – Lukas Kalbertodt Sep 02 '19 at 10:01
  • @LukasKalbertodt I agree that it's a duplicate. I just wish that there was another trait besides `FnMut` that relaxed the lifetime requirements. I'm sure that the iterator method I'm calling would be happy to use that instead. – timotree Sep 02 '19 at 14:24

0 Answers0