Here's a minimal example of the issue I'm having:
struct S<'a> {
value: &'a mut Option<()>,
}
impl<'a> S<'a> {
fn f<'b>(&'b mut self) {
*self.value = Some(());
let value: &'a () = self.value.as_ref().unwrap();
}
}
Error:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:8:34
|
8 | let value: &'a () = self.value.as_ref().unwrap();
| ^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the method body at 6:7...
--> src/lib.rs:6:7
|
6 | fn f<'b>(&'b mut self) {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:8:23
|
8 | let value: &'a () = self.value.as_ref().unwrap();
| ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 5:6...
--> src/lib.rs:5:6
|
5 | impl<'a> S<'a> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:8:23
|
8 | let value: &'a () = self.value.as_ref().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The issue is that I'm expecting f's value variable to have the lifetime 'a as I've annotated, but the borrow checker is only content if it's 'b. I need it to be 'a because in my real code I derive a value from it that expects the 'a lifetime. And it also makes sense to me that it should be 'a because (and this is the crux of my confusion:) in self.value I've dereferenced 'b away and should be left with &'a mut Option<()>, i.e. a value with (just) the lifetime 'a.
I can solve it by specifying 'b: 'a but it's actually the opposite (if anything I need 'a: 'b); and also if 'b: 'a then this function mutably borrows indefinitely and I can't touch the S after calling f which is a problem Playground.
I'm not sure if it's overconservative or if I'm actually trying to do something unsound. Looking at the lifetimes at the call-site it makes perfect sense though.
Some information about my real use case: what I have is a buffer of type B, and from that buffer I can derive a value of type T. T isn't just derived from B, it also has a reference to it (imagine fn derive<'a>(self: &'a B) -> T<'a>). T values expire and require management, so I made a manager struct M, and this is where the trouble is: M contains a mutable reference to a B and a cached T. Therefore inside M, the B reference has some lifetime, and T has it too since T refers to B. It's something like this:
struct B { ... }
struct T<'a> { ... }
struct M<'a> {
b: &mut 'a Option<B>,
t: T<'a>,
}
So as in my minimal example, I try to obtain the reference of the B (which I expected to have the lifetime of the buffer but it has the lifetime of M) so I could derive from it and then assign the result to the cached T, but I don't have the right lifetime.