I have encountered a certain behavior of the borrow checker that I find rather odd: if I have a &'a mut &'b mut T
where 'b: 'a, T: 'b
, it seems as though I should be able to treat it as just a &'b mut T
, since I can guarantee that I have mutable access to the T
for at least as long as 'b
. So, in its simplest form, (I think) I should be able to make a function such as this:
fn f<'a, 'b: 'a, T: 'b>(x: &'a mut &'b mut T) -> &'b mut T {
*x
}
However, the borrow checker doesn't like that, saying
error[E0623]: lifetime mismatch
--> src/main.rs:6:5
|
5 | fn f<'a, 'b: 'a, T: 'b>(x: &'a mut &'b mut T) -> &'b mut T {
| -----------------
| |
| these two types are declared with different lifetimes...
6 | *x
| ^^ ...but data from `x` flows into `x` here
My primary question is, why?
My secondary question is, are there safe ways to work around this?
I'm aware that I can cast it to a pointer and then turn it back into a reference, magically summoning whatever lifetime I want in the process, but that requires unsafe
code. I would like to know if there are safe ways to do this, either in general or for specific circumstances (including circumstances in which specific unsafe
code can be verified by the programmer to be safe).
As an example, my actual use case is an iterator that returns mutable references like std::slice::IterMut<'a, T>
and that family of iterators; I have something along the lines of
struct IterMut<'a, T> {
source: &'a mut MyContainer<T>,
... /* other data for iterating */
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<&'a mut T> {
...
}
}
The problem is that inside the next
method, I can only access the source
reference through the &mut self
, effectively creating a &mut &'a MyContainer<T>
, which restricts my ability to borrow from source
to the anonymous lifetime from &mut self
, a la this question.
So in summary, why is this like this, and what steps can I take to avoid this problem?