I'm writing some code in Rust for generating the first 500 numbers in the Collatz sequence of 46445645645564584.
use std::fmt::Debug;
//Calculate the first 500 numbers in the Collatz sequence of 46445645645564584
fn main() {
let mut v = vec![46445645645564584];
for _ in 0..500 {
let last = v[v.len() - 1];
v.push(next(last));
}
print_array(&v);
}
fn next(n: i64) -> i64 {
if n % 2 == 0 {
n / 2
} else {
3 * n + 1
}
}
fn print_array<T: Debug>(v: &[T]) {
for x in v {
println!("{:?}", x);
}
}
This works, but I want to inline the variable last
:
for _ in 0..500 {
v.push(next(v[v.len() - 1]));
}
In my eyes, this should not change the semantics of the program, since I've simply inlined a variable. However, the Rust compiler gives the following error when I try to compile this:
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:9:21
|
9 | v.push(next(v[v.len() - 1]));
| - ^ - mutable borrow ends here
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:9:23
|
9 | v.push(next(v[v.len() - 1]));
| - ^ - mutable borrow ends here
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
As I see it, the immutable borrow of v
should be dropped right when the value v[v.len() - 1]
is computed and passed to next()
. That means the mutable borrow of v
would be successful in the outermost call to v.push()
, since the previous borrow was dropped. Am I seeing this wrong? Or is this a compiler bug?
I am aware you could also do this with iterators/generators, but I'd like to know why this is happening in this specific piece of code, since this might be a problem I'll run into again at some point.