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?

4
  • 'b: 'a means that 'b is at least as long as 'a; i.e. 'a may end before 'b. see e.g. here. your function signature would work if you returned &'a mut T (i.e. the shorter lifetime, where x is guaranteed to be valid). Commented May 11, 2021 at 4:49
  • 3
    What you want is unsound, it could be used to get multiple mutable references to the same object. playground link Commented May 11, 2021 at 4:59
  • 1
    Since you bring up iterators, this may answer your question. Commented May 11, 2021 at 5:15
  • @kmdreko Ah, yes this makes sense now, thanks. If you make those into an answer I'll accept it. Commented May 11, 2021 at 18:06

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.