2

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?

Francis Gagné
  • 60,274
  • 7
  • 180
  • 155
Anonymous
  • 491
  • 2
  • 12
  • `'b: 'a` means that `'b` is at least as long as `'a`; i.e. `'a` may end before `'b`. [see e.g. here](https://doc.rust-lang.org/rust-by-example/scope/lifetime/lifetime_coercion.html). your function signature would work if you returned `&'a mut T` (i.e. the shorter lifetime, where `x` is guaranteed to be valid). – hiro protagonist May 11 '21 at 04:49
  • 3
    What you want is unsound, it could be used to get multiple mutable references to the same object. [playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=eedd88a1a33dc2e8dade8b4c9bd18342) – kmdreko May 11 '21 at 04:59
  • 1
    Since you bring up iterators, [this](https://stackoverflow.com/questions/25730586/how-can-i-create-my-own-data-structure-with-an-iterator-that-returns-mutable-ref) may answer your question. – kmdreko May 11 '21 at 05:15
  • @kmdreko Ah, yes this makes sense now, thanks. If you make those into an answer I'll accept it. – Anonymous May 11 '21 at 18:06

0 Answers0