50 | let cd = &mut rsv.x.mut_slice(0..1);
| ^^^^^
| |
| `rsv.x` was mutably borrowed here in the previous iteration of the loop
| first borrow used here, in later iteration of loop
The logic here is, I have storage data structure say Vec and I want to create various mutable views on top of it. Inside a loop, I am updating some portion of the underlying Vec.
Why would the previous borrow persists in the next loop? There is no later reference to the mut reference?
that’s an instance of the anti-pattern &'a mut SomeType<'a> (in the type of self). Such a reference, where the reference’s lifetime is the same as a lifetime inside of the type and the reference is mutable, is essentially never what you want. Once you create it, the value is borrowed mutable for it’s entire duration of existence, since the borrow lives as long as the value itself can exist (due to the lifetimes being the same). In the loop, you try to borrow it like this twice which thus fails. (Types that implement Drop[1] would not even permit such a borrowing once.
This signature is probably motivated by compiler errors that suggested the change, so the underlying problem is likely something else. (Often, the attempt to create self-referencing data structures.)
(It’s a bit unfortunate that the compiler still isn’t improved to avoid generating suggested fixes that create this anti-pattern. Assuming this was the case here to begin with.)
Have you read @quinedot 's guide (link)? The mut_slice method looks a little fishy. Its return value has the same lifetime as the original object which is very restrictive.
So upon second look (and a minute of trying out changes to the signature of mut_slice) my conclusion is that this might have been a case of a different way to accidentally arrive at &'a mut SomeType<'a>: not paying attention and accidentally using too few different lifetimes in your code.
Once you create it, the value is borrowed mutable for it’s entire duration of existence, since the borrow lives as long as the value itself can exist (due to the lifetimes being the same).
My takeaway on this is, even though the variable cd goes out of scope after the current loop, the function signature of mut_slice says the mutable borrow will last for the entire duration of the existence of rsv.x, thus compiler will complain on the 2nd loop. Is this the right understanding?
It's the right understanding. Though note that it's even worse than "2nd time through the loop" -- you can't use rsv.x directly ever again, because it's forever exclusively borrowed. That includes using the rsv as a whole (obtaining a &rsv or &mut rsv or moving rsv[1]). Examples.
References going out of scope doesn't generally mean much lifetime-wise. If you have a borrow of the reference itself (e.g. let x = &cd), those can't outlast the reference going out of scope. But any of the lifetimes in the reference's type can be longer than the scope.
you could still use other fields, if it had any ↩︎
References going out of scope doesn't generally mean much lifetime-wise
TIL, super helpful.
Yeah...I read your post on that (mentioned by @user16251 ) and the whole thing is exclusive borrowed. Feeling progressed quite a bit on understanding lifetime from this discussion.