Hacker News new | ask | show | jobs
by agons 306 days ago
Is there a reason the Zig compiler can't perform type-narrowing for `u` within the `U::A(_) | U::B(_)` "guard", rendering just the set of 2 cases entirely necessary and sufficient (obviating the need for any of the solutions in the blog post)?

I'm not familiar with Zig, but also ready to find out I'm not as familiar with type systems as I thought.

1 comments

it can narrow the payload: https://zigbin.io/7cb79d

I think the post would be more helpful if it had a concrete use case. let's say a contrived bytecode VM:

  dispatch: switch (instruction) {
      inline .load, .load0, .load1, .load2, .load3 => |_, tag| {
          const slot = switch (tag) {
              .load => self.read(u8),
              else => @intFromEnum(tag) - @intFromEnum(.load0),
          };
          self.push(self.locals[slot]);
          continue :dispatch self.read(Instruction);
      },
      // ...
  }
"because comptime", this is effectively the same runtime performance as the common:

  dispatch: switch (instruction) {
      .load => {
          self.push(self.locals[self.read(u8)]);
          continue :dispatch self.read(Instruction);
      },
      .load0 => {
          self.push(self.locals[0]);
          continue :dispatch self.read(Instruction);
      },
      .load1 => {
          self.push(self.locals[1]);
          continue :dispatch self.read(Instruction);
      },
      .load2 => {
          self.push(self.locals[2]);
          continue :dispatch self.read(Instruction);
      },
      .load3 => {
          self.push(self.locals[3]);
          continue :dispatch self.read(Instruction);
      },
      // ...
  }
and this is in a situation where this level of performance optimization is actually valuable to spend time on. it's nice that Zig lets you achieve it while reusing the logic.