17

What am I doing wrong with the variable i below? Why does the compiler say I cannot index a Vec with a u32 and how do I fix it?

fn main() {
    let a: Vec<u32> = vec![1, 2, 3, 4];
    let number: u32 = 4;
    let mut count = 0;
    
    for i in 0..number {
        if a[i] % 2 != 0 {
            count += 1;
        } else {
            continue;
        }
    }
    println!("{}", count);
}

Error:

error[E0277]: the type `[u32]` cannot be indexed by `u32`
 --> src/main.rs:7:12
  |
7 |         if a[i] % 2 != 0 {
  |            ^^^^ slice indices are of type `usize` or ranges of `usize`
  |
  = help: the trait `SliceIndex<[u32]>` is not implemented for `u32`
  = note: required because of the requirements on the impl of `Index<u32>` for `Vec<u32>`

Playground

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Masaki Imai
  • 181
  • 1
  • 1
  • 3

3 Answers3

18

Indexing is made possible by Index and IndexMut traits.

You are using a Vec and it implements Index and IndexMut traits.

Although, it imposes a trait bound that type used to index should implement SliceIndex<[T]>:

impl<T, I> Index<I> for Vec<T>
where
    I: SliceIndex<[T]>

SliceIndex is implemented for usize because of which it is possible to use type usize as index.

It is not implmented for u32 because of which you can't use u32 as index.

i has a type u32 because it is received from the range 0..number where number has type u32.


A simple fix would be to cast i to usize:

if a[i as usize] % 2 != 0

This cast can be safely done as long as you are on at least a 32 bit machine.

As per the definition of usize:

The size of this primitive is how many bytes it takes to reference any location in memory


Moreover, your code doesn't require you to use u32. Instead you should use usize from the start.

Mihir Luthra
  • 6,059
  • 3
  • 14
  • 39
7

Quick remark: instead of changing the type of number to usize forever or constantly casting i to usize one may use the following construction which casts number to usize for the purposes of the for loop only:

fn main() {
    let a: Vec<u32> = vec![1, 2, 3, 4];
    let number: u32 = 4;
    let mut count = 0;

    for i in 0..number as usize {
        if a[i] % 2 != 0 {
            count += 1;
        } else {
            continue;
        }
    }
    println!("{}", count);
}
3

Change the type of number to usize, so the range for i in 0..number will also iterate over usizes. Indexing is typically done with usize