Zig refuses to do simple bit manipulation

I’m completely lost here. I just started with Zig two days ago and I’ve been testing it out with some simple code snippets. However, I’ve been stuck for the past few hours while doing simple bit twiddling. This code won’t compile:

const expect = @import("std").testing.expect;

fn is_bit_set(x: u64, n: u6) bool {
  return x & (1 << n) != 0;
}

test "doesn't work" {
  try expect(is_bit_set(0xA000, 13) == true);
}

I don’t understand the error message either:

bit_test.zig:4:17: error: LHS of shift must be a fixed-width integer type, or RHS must be comptime-known
  return x & (1 << n) != 0;
              ~~^~~~

I made sure that n is a u6 instead of a u64 or usize (due to the compiler complaining), but now I get this error.

Hm…
https://github.com/ziglang/zig/issues/8395

I dont have a computer with me so I cant test it, but try to explicitely declare the 1 as a u64 by writing

@as(u64, 1)

I think the compiler can’t infer the type here.

After reading the issue Durobot linked, I am wondering what version youre using

You have to tell it what the bit width of the integer literal should be (with @as like markus said), otherwise the exact semantics of the left shift are not well defined.

see: The Zig Pastebin

I’m using 0.10.1. Coercion to a u64 worked, but I’m surprised Zig couldn’t automatically infer the type. It seems like it’d be annoying to constantly cast RHS bit shift operands to a u6 and then explicitly cast integer literals to the desired type.

1 Like

Why should (1 << n) be a u64 instead of, say, a u128? Why is x the defining type rather than (1 << n)? Why should n being u6 imply anything about the type of (1 << n)?

Zig, by and large, does not assume or imply. In addition, it tends not to walk large dependency chains to find out anything about types in order to keep compilation fast.

2 Likes