I don’t think that is the most reasonable desugaring, though it appears to be what the Rust compiler is currently doing. I think this is what should be done:
{
// evaluate outer vec.
let a = {
// evaluate inner vec.
let v_ref = &vec;
Vec::len(v_ref)
};
let v_mut_ref = &mut vec;
Vec::push(v_mut_ref, a);
}
In particular, even the though compiler needs to evaluate the leftmost vec first, it doesn’t need to borrow it at that time; it only needs to borrow it mutably just before Vec::push() is called.
Consider this:
fn len_mut<T>(vec: &mut Vec<T>) -> usize {
vec.len()
}
That shows that we can create a non-mut reference even though a mut reference to the object exists.
Now consider this:
fn len_then_push(vec: &mut Vec<usize>) {
let len = vec.len();
vec.push(len);
}
This shows that we can use a mut reference after we’ve used the reference in a non-mut context.
Now consider this:
fn push_len(vec: &mut Vec<usize>) {
vec.push(vec.len());
}
This should be exactly like len_then_push(), but instead it fails to compile because vec is borrowed mutably too early.
Here’s this code on play.rust-lang.org: https://is.gd/CYnjtF