I've recently published a crate (https://crates.io/crates/rsor), which mostly works as intended, but there is one lifetime issue I need help with.
Let me start with an example that does work correctly (AFAICT):
The main struct
in my crate has a method like this:
pub fn fill<'a, 'b, F>(&'a mut self, f: F) -> &'a [&'b T]
where
F: FnOnce(Vec<&'b T>) -> Vec<&'b T>,
{
/* ... */
}
The idea behind the different lifetimes is that lifetime 'a
depends on my struct, but lifetime 'b
only depends on the input to the method, so it should be able to live on even after my struct is destroyed.
And alas, this seems to work in a (quite contrived) example:
use rsor::Slice;
fn main() {
let data = 'a';
let outer_reference = {
let mut reusable_slice = Slice::new();
let chars = reusable_slice.fill(|mut v| {
v.push(&data);
v
});
chars[0]
};
assert_eq!(*outer_reference, 'a');
}
My struct reusable_slice
goes out of scope, but outer_reference
still lives.
Now to my problem: I would like to do the same thing with mutable references.
I have a mutable version of the method mentioned above:
pub fn fill_mut<'a, 'b, F>(&'a mut self, f: F) -> &'a mut [&'b mut T]
where
F: FnOnce(Vec<&'b mut T>) -> Vec<&'b mut T>,
{
/* ... */
}
This should be exactly the same thing as before, except the immutable references have been replaced with mutable references.
I would like to have a similar example as above, just with mutable references:
use rsor::Slice;
fn main() {
let mut data = 'a';
let outer_reference: &mut char = {
let mut reusable_slice = Slice::new();
let chars = reusable_slice.fill_mut(|mut v| {
v.push(&mut data);
v
});
&mut chars[0]
};
*outer_reference = 'z';
assert_eq!(data, 'z');
}
Sadly, this doesn't compile:
error[E0597]: `reusable_slice` does not live long enough
--> lifetime-problems.rs:7:21
|
7 | let chars = reusable_slice.fill_mut(|mut v| {
| ^^^^^^^^^^^^^^ borrowed value does not live long enough
...
11 | &mut chars[0]
| ------------- borrow later used here
12 | };
| - `reusable_slice` dropped here while still borrowed
There is one notable difference in the code (except for using mutable references): I had to explicitly provide the type &mut char
for outer_reference
because the compiler complained, but I'm not sure whether this has anything to do with the problem.
My questions are:
Why does changing &T
to &mut T
change the lifetimes in this case?
And more importantly: how can I get my example to compile (and work correctly)?
The source code of the crate is here: https://github.com/mgeier/rsor
Here is a branch that includes the broken example (and the working one as well) as a doctest: https://github.com/mgeier/rsor/tree/lifetime-example-broken
The error can be reproduced by running cargo test
.