- let c = move |mut rpass: RenderPass| {
+ let c = |mut rpass| {
rpass = triangle(rpass, &p);
};
There's something subtle going on. By writing out the type (with elided lifetime), the closure shall accept RenderPass<'a> for any lifetime 'a, which could live longer than p, resulting the error. If you omit that, then the compiler can infer the correct lifetime bounds.
Basically, this issue could be simplified to this snippet:
fn main() {
let i = 1;
- let x = |mut x: &i32| { x = &i; };
+ let x = |mut x| { x = &i; };
}
Another way to fix the error is do not reassigning the out pipeline to he origin variable. But declare a new variable instead.
let c = move |mut rpass: RenderPass| {
- rpass = triangle(rpass, &p);
+ let rpass2 = triangle(rpass, &p);
};
This way, rpass2 and rpass can have different lifetime, so p is not required to outlive any rpass. (rpass's lifetime will be shortened to local scope when being passed to triangle.)
I do feel like I want to try passing RenderPass as a mutable reference to the triangle function. Is there a more simple scenario to explain why this doesn't work?
Because the type is covariant (in the example at least), you can introduce a new binding to shorten the lifetime the caller chose to pass in to a lifetime that is shorter than the closure body:
- let c = move |mut rpass: RenderPass| {
+ let c = move |rpass: RenderPass<'_>| {
+ let mut rpass = rpass;
triangle(&mut rpass, &p);
};
Or...
- let c = move |mut rpass: RenderPass| {
+ let c = move |mut rpass @ _: RenderPass<'_>| {
...but even less people will understand why that works (it effectively desugars as the fix above).
If your actual structure is not covariant, it can't work because the caller chooses the lifetime, and callers can't name/choose lifetimes shorter than your function body. So it would be impossible to borrow the captured p for long enough in the closure body, just like you can't borrow a local variable for as long as some caller-chosen lifetime in a function body.