I want to uncomment this line, but I cant move value from mutable reference. I write a workaround using special junk value, but what if I use type without "default" or "junk" values with heavy destructor?
What should I write in this case.
Also this code works, I don't know why:
fn main() {
let mut s = State{i: 42};
while s.i > 0 {
s = s.next();
}
}
Did you read this section? The borrow checker certainly needs to think about such situations in order to uphold Rust's guarantees, and thus you need to think about it when it causes an error such as this.
You may say "but I know next never panics"; however, function calls are an API boundary in Rust -- the compiler isn't going to examine the body of the function to see if it might panic or not, and instead always treats it like it might. That way the implementor of next is free to change the function body code without breaking upstream. It would be too annoying if adding any potentially-panicking operation in next suddenly caused far-away code to break.
And incidentally, your example next could panic on underflow: arithmetic on primitive integers are potentially-panicking operations.
Rust doesn't have anything like noexcept, at least not yet. Crates like borrow_with fill that niche instead, by turning any panics into aborts or similar.
I interpreted @T4r4sB's post as lamenting that Rust has (recoverable unwinding) panics at all, since if it didn't then the compiler wouldn't need to ban this case of temporarily moving out from a &mut.
No, banning recoverable panics is not enough, you need to also ban unwinding, i.e. running destructors of local variables when a panic happens. If you don't do that then you'll end up running the destructor of the value that was moved out of, which is invalid. Also, the destructor of any value that was holding a reference to the moved out of value may also access it.
This effectively means turning panics into aborts.