Hi, I am trying to compile a piece of code that IMO does not break lifetime rules but the compiler is not allowing me to.
I constructed a minimal example below. Assume that build_compare is an external library that I have no control over, and that the signature of some_compare cannot change, i.e. it cannot be a Vec or something that does not require an allocation. I am trying to return a new DynComparator on top of the one returned by build_compare (essentially build_compare is a factory, and I am decorating that factory).
My expectation is that because values_right and values_left was passed to build_compare, it should be moved to inside the closure, but this is not really happening, and I have been unable so far to move them to inside the closure.
Because compare is never used outside the closure, I would expect this to be fine, as there is nothing outliving.
use std::cmp::Ordering;
pub type DynComparator<'a> = Box<dyn Fn(usize, usize) -> Ordering + 'a>;
fn build_compare<'a>(left: &'a Vec<i32>, right: &'a Vec<i32>) -> DynComparator<'a> {
Box::new(move |i: usize, j: usize| {
left[i].cmp(&right[j])
})
}
fn some_compare<'a>(
keys_left: &'a[i32], values_left: &'a[i32],
keys_right: &'a[i32], values_right: &'a[i32]
) -> DynComparator<'a> {
let values_left = values_left.to_vec();
let values_right = values_right.to_vec();
let compare = build_compare(&values_left, &values_right);
Box::new(move |i, j| {
let key_left = keys_left[i] as usize;
let key_right = keys_right[j] as usize;
(compare)(key_left, key_right)
})
}
fn main() {
let a = vec![0i32];
let b = vec![1i32];
let c = vec![0i32];
let d = vec![1i32];
let cmp = some_compare(&a, &b, &c, &d);
println!("{:?}", (cmp)(0, 0));
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0515]: cannot return value referencing local variable `values_right`
--> src/main.rs:21:5
|
19 | let compare = build_compare(&values_left, &values_right);
| ------------- `values_right` is borrowed here
20 |
21 | / Box::new(move |i, j| {
22 | | let key_left = keys_left[i] as usize;
23 | | let key_right = keys_right[j] as usize;
24 | | (compare)(key_left, key_right)
25 | | })
| |______^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing local variable `values_left`
--> src/main.rs:21:5
|
19 | let compare = build_compare(&values_left, &values_right);
| ------------ `values_left` is borrowed here
20 |
21 | / Box::new(move |i, j| {
22 | | let key_left = keys_left[i] as usize;
23 | | let key_right = keys_right[j] as usize;
24 | | (compare)(key_left, key_right)
25 | | })
| |______^ returns a value referencing data owned by the current function
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0515`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.