The main idea is, I have a function that mutates the internal state of Foo, and then returns a reference to something within Foo. Then, I'd like to call that multiple times, until the returned value meets a condition. This code does not compile, as the break v wants to borrow self, but self was already borrowed in the previous iteration of the loop.
I can't figure out how to do this without reworking my incr_and_ret method. In my actual code, incr_and_ret reads from a TCP stream, and so I'd like to modify internal state, while returning something unique to that call.
So my question has two parts: firstly, why is this disallowed? I cannot figure out why my borrow is being held between iterations of the loop. And secondly, is this possible right now? Or do I need to restructure my code?
In the case where the value is returned, the call to incr_and_ret has to take an exclusive borrow that's longer than the body of incr_to_10, and the current borrow checker can't distinguish between that call and a call that loops. Also known as, conditional return of a borrow. The next-gen borrow checker should allow it.
When you borrow self with &mut, you borrow it exclusively. You borrow it for the entire scope where self is used and the scope where the returned &i32 is used. By combining that loan you get worst of both worlds — the restrictions of &mut self, and the large scope of the returned &i32.
Rust has no syntax to express that you want to "downgrade" the &i32 reference, and it can't do that automatically, because there are edge cases where it would be unsafe.
In the version where you return &self.number, you end the &mut self loan from incr_and_ret, and start a new non-exclusive loan for &self.number only. These two operations are independent inside the incr_to_10 function, so they work, but they still end up being related by an elided lifetime outside of incr_to_10 function, like incr_and_ret was.
Ah, this is super interesting to read about, and the Polonius crate looks pretty sweet. Thanks!
Ok, that's the bit that had me confused. I'm somewhat used to rust shortening lifetimes automatically, so I was a bit surprised when it didn't turn this into an immutable borrow. Thank you!