Cannot cast `usize` to `i64` in `std.math.pow`

I’m trying loop over a set of bytes to convert them to a number. However, I get weird error where it complains about u6 not being convertable to i64.
This code shows the same error:

const std = @import("std");

fn foo(input: []const u8) void {
    var acc: i64 = 0;
    for (0..4) |pow| {
        acc += (@as(i64, @intCast(input[pow + 1]))) << std.math.pow(i64, 8, @as(i64, @intCast(pow)));
    }
}

pub fn main() !void {
    const input: []const u8 = "\xFF";
    foo(input);
}

And the error on compiler explorer is this:

example.zig:6:68: error: expected type ‘u6’, found ‘i64’
example.zig:6:68: note: unsigned 6-bit int cannot represent all possible signed 64-bit values
Compiler returned: 1

I am very confused and would like some help understanding what’s going wrong. To me there is no problem casting these usizes to i64s and the u6 in the error message seems completely unrelated to the actual error.

In a << b, b must be comptime-known or have a type with log2 number of bits as a, see Bit Shift Left in langref’s table of operators.

Here’s a working case:

const std = @import("std");

fn foo(input: []const u8) void {
    var acc: u64 = 0;
    for (0..4) |pow| {
        acc += @as(u64, input[pow + 1]) << @as(u6, @truncate(std.math.pow(usize, 8, pow)));
    }
}

pub fn main() !void {
    const input: []const u8 = "\xFF\xFF\xFF\xFF\xFF";
    foo(input);
}
1 Like

That does indeed compile! Probably should have figured that the 6 came from a log2 but I was too confused.