Why are range variables always usize?

The for loop mainly exists to iterate over slices. For example:

const slice: []u8 = ...
for(slice[a..b], a..b) |val, index| {...}

That’s why for(a..b) has the same restrictions as slice[a..b], that being:

  • b must be greater than or equal to a
  • a and b must fit inside a usize (→ only positive values are allowed)

Note that your example only works like this because a and b are comptime known. If they are runtime-known isize you will get an earlier compiler error:

var a: isize = 1;
_ = &a;
var b: isize = 10;
_ = &b;
var sum: isize = 0;
for (a..b) |i| { // error: expected type 'usize', found 'isize'
	sum += i;
}

So the lower bound can’t be negative.

Here is a proposal for that on github: Proposal: Infer type on ranged for loops from the type of the range values instead of defaulting to usize · Issue #14704 · ziglang/zig · GitHub
It was rejected by Andrew due to implementation problems.

5 Likes