In (an artificial simplification of) my project, I have a struct ContainsData
which can only be modified through a handle HoldsRef<'a>
, which holds a ref to some field in ContainsData
. In addition, after use of the handle, some cleanup
method must be called.
struct ContainsData(i64);
impl ContainsData {
fn cleanup(&mut self) {
self.0 = self.0.abs();
}
}
struct HoldsRef<'a>(&'a mut i64);
impl<'a> HoldsRef<'a> {
fn set(&mut self, value: &'a i64) {
*self.0 += value;
}
}
// A typical interaction with "ContainsData"
fn main() {
let mut container = ContainsData(5);
let x = 32;
let mut handle = HoldsRef(&mut container.0); // _
handle.set(&x); // | A
handle.set(&31); // |
container.cleanup() // v
}
I would like to replace A with a single method call to ContainsData
. All modifications to the handle will be done in the context of closure as follows:
impl ContainsData {
fn modify(&mut self, continuation : impl Fn(HoldsRef)) {
let handle = HoldsRef(&mut self.0);
continuation(handle);
self.cleanup()
}
}
fn main2() {
let mut container = ContainsData(5);
let x = 32;
container.modify(|mut handle| {
handle.set(&x);
handle.set(&32);
});
}
This does not compile:
error[E0597]: `x` does not live long enough
--> src/main.rs:56:21
|
55 | container.modify(|mut handle| {
| ------------ value captured here
56 | handle.set(&x);
| ------------^-
| | |
| | borrowed value does not live long enough
| argument requires that `x` is borrowed for `'static`
...
59 | }
| - `x` dropped here while still borrowed
First question: why does Rust consider that x
is borrowed for 'static
? I assume it has to do with the elision rule for Fn(HoldsRef)
but I can't quite figure it out what the rule says in that case.
Second question: is there a way to change the signature of modify
or alter the code a little bit to be able to replace A with a single method call ? I have tried to annotate lifetimes in various to no avail.
fn modify<'a>(&mut self, continuation : impl Fn(HoldsRef<'a>))
// cannot infer an appropriate lifetime (b/c, I guess, the handle has a lifetime strictly smaller than the function)
Broader context: HoldsRef<'a>
is actually wgpu::RenderPass<'a>. I don't have the option to change the signature of the method set
.