Inconsistent compiler behaviour

Hi!

While solving an exercise, I was sad to learn that in zig @intFromBool() returns a type u1 which meant I couldn’t chain them together:

fn equalSidesCount(self: Triangle) u8 {
    return @intFromBool(self.a == self.b) +
        @intFromBool(self.a == self.c) +
        @intFromBool(self.b == self.c);
}
$ zig test test_triangle.zig 
thread 27344997 panic: integer overflow
/path/to/triangle.zig:10:47: 0x102c36d0f in equalSidesCount (test)
        return @intFromBool(self.a == self.b) +
            @intFromBool(self.a == self.c) +
            @intFromBool(self.b == self.c);

So I worked around that limitation by wrapping them all inside a @as(u8).

fn equalSidesCount(self: Triangle) u8 {
    return @as(u8, @intFromBool(self.a == self.b)) +
        @as(u8, @intFromBool(self.a == self.c)) +
        @as(u8, @intFromBool(self.b == self.c));
}

This solution worked but it looked a bit too verbose. I submitted it and since I couldn’t afford mentors anymore with my reputation, I went to ask on zig’s official IRC channel if there was a better way.

torque | you only need to wrap one of them in the @as(u8)
torque | the rest will be promoted

Great news! I updated my answer:

fn equalSidesCount(self: Triangle) u8 {
    return @as(u8, @intFromBool(self.a == self.b)) +
        @intFromBool(self.a == self.c) +
        @intFromBool(self.b == self.c);
}

And tested locally:

$ zig test test_triangle.zig
All 21 tests passed.

Great! It worked! So I re-submitted my answer.

Only on Exercism’s server, it didn’t compile. Ok no panic, let’s look at the compiler’s error message:

triangle.zig:10:24: error: invalid builtin function: '@intFromBool'
        return @as(u8, @intFromBool(self.a == self.b)) +
            @intFromBool(self.a == self.c) +
            @intFromBool(self.b == self.c);

How come? @intFromBool() worked for my first iteration when it was wrapped inside @as(), just by removing @as() it stops being a valid builtin? That has to be a bug, right?

(BTW, I have zig 0.13.0 on a Mac)

1 Like

FWIW it looks like Zig introduced that function in 0.11.0 and the test runner uses 0.13.0.

Yes, If the test runner used an old version, that would be somewhat okay, I would write zig 0.10 code and everything would be fine. The issue I am reporting is that it seems the test runner switches versions between runs (“inconsistent compiler behaviour”). I’m saying this because in the first run @intFromBool() was recognized and worked as intended and in the second run, it wasn’t recognized at all

EDIT: If I could re-submit the same code, I feel like it would work :sweat_smile:

In theory, IIUC, the test runner environment should not change between runs unless the test runner code changes.

As I expected, I’ve replaced a >= 1 with a > 0 just so I could re-submit an iteration 3, and it compiled.

I don’t know if admins can check what happened with the test-runners for my Iteration 2 on the exercice “Triangles”