Why did Rust decide to only allow usize
as index values and not accept isize
?
After having read multiple threads about the topic here, I still don't understand the benefit of it.
In most cases, usize
indexes are perfectly usable. However, some algorithms require signed arithmetic to compute an index. Vector traversal, some convolution filters, etc. In that case, I need to use isize
to compute the value of the index.
Usually, relevant code is inside a loop and looks something like this:
let i: isize = /* some signed integer arithmetic */;
v[i as usize] = 42;
The as usize
part can really get out of hand. As algorithmic complexity increases, the number of indexing operations grows. And the as usize
part only adds boilerplate to the code without any clear benefits that I see.
What if Rust accepted isize
as an index?
1. There would be the same amount of runtime checks required.
If Rust accepted isize
as an index (v[i] = 42;
), then the indexing operation's range check would have to perform a negativity test. Which is the same test that the as usize
explicit conversion performs, so there is no performance benefit of converting to usize
at all.
2. There would be the same amount of compile-time checks.
If the compiler can deduct the value being negative, then it harms the usize
conversion equally bad and the indexing range check. So there should be the same amount of warnings and errors in either case.
3. The code would be easier to read and to write
Many bought up this question before, and I wouldn't type this lengthy post if the amount of as usize
boilerplates wouldn't be a concern to us. It is not a serious issue, but definitely hinders the readability of the code.
Sometimes signed arithmetic is necessary.
Please help me understand this design decision.