let mut arr = [1, 2];
let a = &mut arr[0];
let b = &mut arr[0];
This code could be allowed: let mut arr = [1, 2];
let a = &mut arr[0];
let b = &mut arr[1];
And it gets Hard once variable indexes are involved. And since the whole point of using arrays is to get variable indexing, the Rust developers choose to only implement reborrowing for structs and tuples. fn main() {
let mut x = 10;
let y = &mut x;
*y = 11;
println!("{}", x);
}
This will complain error: cannot borrow `x` as immutable because it is also borrowed as mutable
This is because an `&mut` borrow is exclusive: while `y` is alive, we cannot use `x`. We can fix this by making a new scope for `y`: fn main() {
let mut x = 10;
{
let y = &mut x;
*y = 11;
}
println!("{}", x);
}
This works, and will print `11`.Non-lexical lifetimes would allow the compiler to demonstrate that these two things are the same, and allow the first one to compile with the behavior of the second.
It's an interesting tradeoff, because right now, the rules are very simple and conservative. Scope is fairly easy to reason about. Non-lexical lifetimes would make certain things easier, but also a bit harder to reason about, because the rules are more complex.
I want memory safety with as few hazzle as possible and that Rust doesn't understand the safety of the first example means hazzle. I expect the compiler to try to understand even if it's ’hard’. It doesn't need to understand everything but the mentioned situtation should be doable.
I'm not sure what you mean by a 'more detailed tradeoff.' You mean a more complicated example?
> I expect the compiler to try to understand even if it's ’hard’.
It's not a matter of difficulty, exactly, it's a matter of how easy it is to understand what the compiler is doing. Figuring out non-lexical scopes means that my mental model of what the compiler is doing is more difficult than it is right now, which may or may not be the right tradeoff. I would say that most people want non-lexical lifetimes/SEME regions to be implemented, though.