Your function is mostly correct. The compiled error "borrowed value does not live long enough" is due to the fact that you are defining your data inside the foo
rather than pass it in. The error is because of the linelet mut data = [1, 2, 3, 4];
The life time of the data
is same as the function foo
because it is created in the function foo
. However, the closure's life time is longer than the variable data
as the closure is passed in as an argument to foo
so its lifetime is longer than data
. When the function foo
goes out of the scope, the data
is dropped. Then your closure's is trying to return a reference data
which is already dropped. This is why you have compiled error "borrowed value does not live long enough".
You can make this compile by passing the data into foo
as an argument, in this case, you will not have the issue due to lifetime.
The below code will compile.
fn foo<'a, I: Iterator<Item = &'a mut i32>>(make_iter: impl Fn(&'a mut [i32]) -> I, data: &'a mut Vec<i32>) {
// let mut data = [1, 2, 3, 4];
make_iter(data);
}
fn main() {
let mut data= vec![1,2,3,4];
foo(|x| x.iter_mut(), &mut data);
foo(|x| x.iter_mut().rev(), &mut data);
}
The rustplay ground link : https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8b263451fcb01518b3f35bda8485af9c
Update: Sry to misunderstand your requirements. I was trying to come out a clean way to write this, but the best I can come up with is using Box<dyn
to do. I know there are runtime cost for Box<dyn...
, but I can't come out a better way using impl Iterator
The implementation using Box<dyn ...
is
fn foo<F>(make_iter: F) where for<'a> F: Fn(&'a mut [i32])->Box<dyn Iterator<Item=&'a mut i32>+'a>{
let mut data = vec![1, 2, 3, 4];
make_iter(&mut data);
}
fn main() {
foo(|x| Box::new(x.iter_mut()));
foo(|x| Box::new(x.iter_mut().rev()));
}