I would like to understand why apply_shorter compiles and why apply_implicit_mut does not.
My issue i am coming from is that I would like to use function with explicit lifetimes, like apply_mut inside trait with implicit liftime (like Iterator.next(&mut self)) In this case using apply works, but apply_mut not.
pub struct MyRefMap<'a, V, F> {
myref: &'a V,
fun: F,
}
impl<'a, 's, V, F, Out> MyRefMap<'a, V, F>
where
F: Fn(&V) -> Out,
'a : 's,
{
pub fn apply<'b>(&'b self) -> Out where 'b : 'a {
(self.fun)(self.myref)
}
pub fn apply_mut<'b>(&'b mut self) -> Out where 'b : 'a {
(self.fun)(self.myref)
}
// this compiles fine / why?
pub fn apply_shorter(&'s mut self) -> Out {
self.apply()
}
// this also compiles / ...
pub fn apply_anon(&'_ mut self) -> Out {
self.apply()
}
// this also compiles (same as previous)
pub fn apply_implicit(&mut self) -> Out {
self.apply()
}
// this one that calls apply_mut() does not compile
pub fn apply_implicit_mut(&mut self) -> Out {
self.apply_mut()
}
}
I believe this is a variance issue. &mut T is invariant over T, so the borrow checker is not allowed to choose a smaller lifetime for 'a. In the non-mut apply method the borrow checker is allowed to pick a shorter lifetime for 'a than the "real" lifetime of the reference which is why that version works.
If we alter the code so there's no lifetime in MyRefMap we can see that the method signatures compile as written