If I have a closure, I can move || ...
to move data into the closure context, like this:
#[derive(Debug)]
struct State {
value: usize,
}
fn external_receiver(mut inc: impl FnMut() -> usize) {
let x = inc();
println!("{:?}", x);
let x = inc();
println!("{:?}", x);
}
fn main() {
let mut foo = Box::new(State { value: 0 });
external_receiver(move || -> usize {
foo.as_mut().value += 1;
return foo.as_ref().value;
});
}
I have a few situations where it would be convenient to have a closure that could return a &mut State
reference to some data object, where the caller of the closure was totally naive about the source of the object.
I can't get anything like that to work though:
#[derive(Debug)]
struct State {
value: usize,
}
fn external_receiver(inc: impl Fn() -> &mut State) {
let x = inc();
x.value += 1;
println!("{:?}", x);
}
fn main() {
let mut foo = Box::new(State { value: 0 });
external_receiver(move || -> &mut State { foo.as_mut() });
}
There doesn't seem to any obvious way around this; I can't seem to figure out how to assert that the lifetime of the returned reference (&'a mut State
) should be equal to the lifetime of the closure itself.
I've tried a couple of variations like passing a reference:
fn external_receiver<'a>(inc: &'a mut FnMut() -> &'a mut State) {
let x = inc();
x.value += 1;
println!("{:?}", x);
}
fn main() {
let mut foo = Box::new(State { value: 0 });
let mut x = move || -> &mut State { foo.as_mut() };
external_receiver(&mut x);
}
...but I get the typical:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:14:45
|
14 | let mut x = move || -> &mut State { foo.as_mut() };
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime as defined on the body at 14:17...
--> src/main.rs:14:17
|
14 | let mut x = move || -> &mut State { foo.as_mut() };
| ^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `foo`
--> src/main.rs:14:41
|
14 | let mut x = move || -> &mut State { foo.as_mut() };
| ^^^
note: but, the lifetime must be valid for the call at 15:5...
--> src/main.rs:15:5
|
15 | external_receiver(&mut x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that argument is valid for the call
--> src/main.rs:15:23
|
15 | external_receiver(&mut x);
| ^^^^^^
Does moving data to a closure not actually move the data into the closure itself (even if the closure is boxed?)?
Is there some way to be able to have a function that basically does Fn() -> &Foo
?