Note that there is a pending RFC on this topic:
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: Rust Playground
In the RFC, there is an example illustrating a proposal to expand your RFC’s proposal. Here’s an expanded version that I think captures more of the subtly:
fn len_then_push(tmp0: &mut Vec<usize>) {
let tmp1 = tmp0.len(); // Used as shared.
Vec::push(tmp0, tmp1); // Used as mutable.
}
fn main() {
// Works fine today.
let mut vec = vec![0];
len_then_push(&mut vec);
// Works fine today as only one reference to `vec` is used.
{
let tmp0 = &mut vec; // `vec` is mutably borrowed.
let tmp1 = tmp0.len(); // Used as shared.
Vec::push(tmp0, tmp1); // Used as mutable.
}
// Now: Fails to compile. Future: OK.
vec.push(vec.len());
// Now: Fails to compile. Future: OK.
{
let tmp0 = &mut vec; // Now: Mutable borrow. Future: reserve `vec`.
let tmp1 = vec.len(); // shared borrow of vec. Now: fails. Future: OK.
Vec::push(tmp0, tmp1); // Future: mutable borrow of `vec` is activated.
}
}
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.