Consider next code:
fn get_ref<'a, R>(slice: &'a Vec<i32>, f: fn(&'a Vec<i32>) -> R) -> R
where
R: 'a,
{
f(slice)
}
fn main() {
let v = [1,2,3,4,5,6];
let iter = get_ref(&v, |x| x.iter().skip(1).take(2));
println!("{:?}", iter.collect::<Vec<_>>());
}
I create some static
variable, then apply some function to its reference and get a result.
It seems to work totally fine. At least it successfully compiles.
Now I am trying to add next level of abstraction. And things are getting weird...
fn owned<'a, R>(owner: Vec<i32>, f: fn(&'a Vec<i32>) -> R)
where
R: 'a,
{
let _ = get_ref(&owner, f); // error occurs here
// `owner` does not live long enough.
}
// get_ref is the same as in the first example
fn get_ref<'a, R>(slice: &'a Vec<i32>, f: fn(&'a Vec<i32>) -> R) -> R
where
R: 'a,
{
f(slice)
}
fn main() {
let v = [1,2,3,4,5,6];
owned(v, |x| x.iter().skip(1).take(2));
}
For me it looks like pretty the same code. But Rust fails to compile it. I really don't understand why this is happening and how should I rewrite my code to compile.
Imagine if I decide to call the function owned<'static, i32>(Vec<i32>, foo)
with foo
defined as:
fn foo(vec: &'static Vec<i32>) -> i32 { ... }
This satisfies the bounds for owned
, since i32: 'static
. However this means that you must have a static reference to call f
, but owner
does not live forever, since it is destroyed at the end of owned
.
One way to fix it is to use the following:
fn owned<R>(owner: Vec<i32>, f: for<'a> fn(&'a Vec<i32>) -> R) {
let _ = get_ref(&owner, f);
}
It says that f
must be callable with any lifetime, rather than just some specific lifetime. However, this has the consequence that R
cannot borrow from the argument, since R
is declared in a larger scope than 'a
. There isn't any way to fix that while keeping the generics as is.
This answer was taken from my response to this thread on URLO.