Data type mismatch

i know this is something really simple but tell me whats wrong with data types , i didnt even manually decided , how did this went wrong? here is code :

fn main() {

    let c = [1..100];

    for number in c.iter() {
        println!("{}",c[number]);
    }
    println!("Hello, world!");
}

here is error

error[E0277]: the trait bound `&std::ops::Range<{integer}>: std::slice::SliceIndex<[std::ops::Range<{integer}>]>` is not satisfied
 --> src\main.rs:6:23
  |
6 |         println!("{}",c[number]);
  |                       ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
  |

[1..100] is a range of i32. You need a range of usize.

so , i should use different loop to fill up empty vector ?

because when i used c : usize , it added one more error

[1..100] is actually an array containing a range, [Range<i32>; 1]. Then .iter() iterates the array as a slice, producing an item of &Range<i32>. You can't index with that, but you could if you cloned it (w/ coercing the integers to usize), producing a new slice, but that would be out of range for c that contains only one item.

1 Like
let c = [1..100]

Creates an array of i32 that is 100 elements in length with the value - 1 of each element the same as the index of the element. So, you would have:

  • c[0] = 1
  • c[1] = 2
  • ...
  • c[99] = 100

So, the indexes of the array go from 0 (usize) to 99 (usize) but the values go from 1 to 100 (i32).

Now, this is going to iterate over the VALUES so that number takes on each of the VALUES in the array which are i32:

for number in c.iter() 

So, you could have on subsequent iterations of the loop:

  • number = 1:i32
  • number = 2:i32
  • ...
  • number = 100:i32

Now, this is going to attempt to use number which is i32 as the index of the array slice:

c[number]; 

Now, number is i32, but, you need a usize. If you cast it to usize, you'd get:

  • c[1] = 2
  • c[2] = 3
  • ...
  • c[99] = 100
  • c[100] = PANIC! Out of index bounds

See the problem now?

1 Like

whats the solution of this ?

Think about what you are trying to do. Analyze what was said. Put on your thinking cap. Draw it out on paper. You'll get there.

2 Likes

No, it doesn't. You can't create an array filled from a range like this.

You can get Rust to show you by purposely forcing a type mismatch, like:

  |
2 |     let c: () = [1..100];
  |                 ^^^^^^^^ expected (), found array of 1 elements
  |
  = note: expected type `()`
             found type `[std::ops::Range<{integer}>; 1]`
1 Like

If your goal is a vector from 1 to 100, and then iterate and print that, use something like:

fn main() {
    let c: Vec<i32> = (1..100).collect();

    for number in c.iter() {
        println!("{}", number);
    }
    println!("Hello, world!");
}
1 Like

changing"for loop" to just "loop" should work right ?

Oops! My mistake. I thought this was some new syntax I wasn't aware of for initializing an array.

That being said, it seems like the OP thought that is what the syntax did too. But, even if it did, it would be wrong for the reasons given.

thanks

No, loop is an infinite loop. If your goal is to print 100 numbers, then that's not the way to do it.

fn main() {

    let c = 1..100;

    for number in c {
        println!("{}", number);
    }
    println!("Hello, world!");
}

That works and prints numbers, because 1..100 (without []) is an iterator over a range of numbers. OTOH [] is an array, so [something] is an array of length 1 containing something.

You can have an array of ranges. Ranges don't contain the numbers, they are just a pair of (start, end) that doesn't contain or do anything until you start iterating it:

fn main() {

    let c = [1..100, 5..20, 3..10, 9..99];

    for range in &c {
        println!("Abstract range from {} to {}", range.start, range.end);
    }
    println!("Hello, world!");
}

Abstract range from 1 to 100
Abstract range from 5 to 20
Abstract range from 3 to 10
Abstract range from 9 to 99
Hello, world!

2 Likes