I can’t understand why Rust complains ("can’t borrow as immutable because also borrowed as mutable") in this code (even considering that .len() is a "constant/harmless" function):
fn main() {
let mut xs1: [i32; 5] = [ 10, 20, 30, 40, 50];
let (slice1, slice2) = xs1.split_at_mut( (xs1.len()/2) ); // <----- ERROR
println!( "{:?}", slice1 );
println!( "{:?}", slice2 );
} // ()
While the split version is fine:
let aux = xs1.len()/2;
let (slice1, slice2) = xs1.split_at_mut( aux );
What’s the rationale here?
Maybe I’m wrong but I always regarded both expressions as "mathematically equivalent" so to say. Not only len() should be a const method but also the input param for split_at_mut() should be const (in C++ parlance).
Still holding this question eight years later?
>Solution :
Maybe I’m wrong but I always regarded both expressions as "mathematically equivalent" so to say.
They are, but this here is an issue with the borrow checker, it is not perfect, and it has limitations.
In fact pretty much all static type systems without holes have will reject valid programs: the choice is to either reject valid programs or accept invalid ones.
And in this case as Sven Marnach notes it’s an artefact of the strict expression evaluation order: if you desugar the call to:
<[_]>::split_at_mut(&mut xs1, xs1.len()/2);
you get the same error.
In essence, Rust interprets
xs1.split_at_mut(xs1.len() / 2)
as
{
let p1 = &mut xs1;
{
let p2 = xs1.len();
{
<[_]>::split_at_mut(p1, p2);
}
}
}
Not only
len()should be aconstmethod
… which it is?
but also the input param for
split_at_mut()should be const (in C++ parlance).
That idea has no relevance to Rust, split_at_mut takes ownership of its (non-self) parameter.