For reasons that are not particularly important in this context, I want to be able to do something very similar to
pub trait MapValue<Out> {
fn map_value<C>(&self, map_func: fn(C, Out), context: C);
}
impl MapValue<i32> for i32 {
fn map_value<C>(&self, map_func: fn(C, i32), context: C) {
map_func(context, *self)
}
}
impl MapValue<&i32> for i32 {
fn map_value<C>(&self, map_func: fn(C, &i32), context: C) {
map_func(context, self)
}
}
for various different types. Unfortunately that fails to compile with
= note: expected fn pointer `fn(&i32, fn(_, &i32), _)`
found fn pointer `fn(&i32, for<'r> fn(_, &'r i32), _)`
If I try to make the lifetime of the i32 explicit as in
impl<'a> MapValue<&'a i32> for i32 {
fn map_value<C>(&'a self, map_func: fn(C, &'a i32), context: C) {
map_func(context, self)
}
}
then it fails with
note: the anonymous lifetime #1 defined on the method body at 12:5...
--> src/main.rs:12:5
|
12 | fn map_value<C>(&'a self, map_func: fn(C, &'a i32), context: C) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 11:6
Obviously I must be doing my lifetime annotations wrong as the call to map_func returns before map_value so it should be impossible that self does not live long enough to be passed into map_func. Any ideas?
EDIT:
I am free to edit the trait and the solution posted by user4815162342 at https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d5763635625281acc066527207b290a7 to switch to
pub trait MapValue<'a, Out> {
fn map_value<C>(&'a self, map_func: fn(C, Out), context: C);
}
does indeed work for the problem that I posted. Curiously it doesn't work in all cases where I use it though. I also have a situation similar to
impl<'a, 'b: 'a> MapValue<'b, &'a i32> for i32 {
fn map_value<C>(&'b self, map_func: fn(C, &'a i32), context: C) {
let cpy = *self; // Something more useful happens here in the real code
map_func(context, &cpy);
}
}
that fails with the following error
14 | map_func(context, &cpy);
| ------------------^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `cpy` is borrowed for `'a`
15 | }
| - `cpy` dropped here while still borrowed
even with the modified trait. I didn't originally post it as I thought it had the same underlying issue as my original second case, but obviously not. Again, I don't see why there would be an issue because the function returns before the variable goes out of scope.