Hi all. This is a stripped-down version of a bigger section of code.
#[derive(Debug)]
enum Output {
Value(String)
}
type Callback<'a> = dyn Fn(&'a [u32]) -> Output + 'a;
struct Thing<'a> {
func: Box<Callback<'a>>
}
impl<'a> Thing<'a> {
fn new<F>(func: F) -> Self
where
F: Fn(&'a [u32]) -> Output + 'a
{
Self { func: Box::new(func) }
}
fn run(&self, numbers: &'a [u32]) -> Output {
(self.func)(numbers)
}
}
fn build_thing<'a>(multiplier: u32) -> Thing<'a> {
Thing::new(
move |v: &'a [u32]| {
let t: u32 = v.iter().sum::<u32>().try_into().unwrap();
Output::Value(format!("RESULT:{}", t * multiplier))
}
)
}
fn main() {
let thing = build_thing(10);
for up_to in 1 ..= 10 {
let numbers: Vec<u32> = (0 .. up_to).collect();
let result = thing.run(&numbers);
println!("{up_to} -> {result:?}");
}
}
The compiler rejects my code:
44 | let numbers: Vec<u32> = (0 .. up_to).collect();
| ------- binding `numbers` declared here
45 | let result = thing.run(&numbers);
| ^^^^^^^^ borrowed value does not live long enough
46 | println!("{up_to} -> {result:?}");
47 | }
| - `numbers` dropped here while still borrowed
48 |
49 | }
| - borrow might be used here, when `thing` is dropped and runs the destructor for type `Thing<'_>`
As far as I understand, the compiler can't tell whether the &numbers
reference is kept inside the thing
object, and thus it complains to me. Please correct me if I'm wrong here.
But the reality is that this isn't the case: the &numbers
reference is used by the closure function placed inside thing
by build_thing()
, but no reference is kept.
I can solve my problem by moving the line let thing = build_thing(10);
inside the for
loop, so that thing
doesn't outlive numbers
anymore. But this would call build_thing()
every loop, I think I can even pay the cost of doing that, but I also would like to do the right thing.
To sum up, there's a way to tell the compiler that no &numbers
reference is kept, so it can compile?