Usize, indexes. When developing in Rust, numeric types like i32 cannot be used as indexes to a slice or vector. This causes an error for new Rust developers.
By casting to usize, we can eliminate the "cannot be indexed" error. This may cause a slight performance cost, so it is best avoided with code changes.
Error example. To begin, we see the code that will cause the "cannot be indexed" error. If we try to run the code that was commented out, the program will not compile.
Tip The variable "i" is a i32 integer, not a usize, because it is the same type as the fields on the Test struct.
struct Test {
start: i32,
end: i32
}
fn main() {
let value = vec![10, 20, 30];
// Create struct with 2 i32 fields.
let test = Test{start: 1, end: 2};
// This won't compile because "i" is not a usize.
for i in test.start..=test.end {
// let element = value[i];// println!("ELEMENT: {}", element)
}
println!("DONE");
}DONEerror[E0277]: the type [{integer}] cannot be indexed by i32
... slice indices are of type usize or ranges of usize
Usize example. Here we see the Rust code that has been corrected to compile and run. We must cast the variable "i" to a usize with the "as" keyword.
Warning This can cause a slight performance decrease, or even lead to incorrect results if the cast is not successful.
struct Test {
start: i32,
end: i32
}
fn main() {
let value = vec![10, 20, 30];
let test = Test{start: 1, end: 2};
for i in test.start..=test.end {
// Change the "i" to a usize to access a vec element.
let element = value[i as usize];
println!("ELEMENT: {}", element)
}
println!("DONE");
}ELEMENT: 20
ELEMENT: 30
DONE
Optimized code. Removing excess work from a loop body can often improve code performance. And performance is one of the key goals of writing Rust.
Here We introduce local variables to hold the loop start and end indexes. We cast them to "usize" outside of the loop.
So In the loop body, the variable "i" is a usize already, so no casting needs to be done. This reduces work.
struct Test {
start: i32,
end: i32
}
fn main() {
let value = vec![10, 20, 30];
let test = Test{start: 1, end: 2};
// Cast once, to avoid casting in the loop body.
let start = test.start as usize;
let end = test.end as usize;
// Loop.
for i in start..=end {
let element = value[i];
println!("ELEMENT: {}", element)
}
println!("DONE");
}ELEMENT: 20
ELEMENT: 30
DONE
Some parts of Rust are confusing and annoying at first. But with some understanding, the "cannot be indexed" issue with usize can be avoided. This can even lead to better code.
Dot Net Perls is a collection of pages with code examples, which are updated to stay current. Programming is an art, and it can be learned from examples.
Donate to this site to help offset the costs of running the server. Sites like this will cease to exist if there is no financial support for them.
Sam Allen is passionate about computer languages, and he maintains 100% of the material available on this website. He hopes it makes the world a nicer place.