While writing a generic serializer for message pack, I came across a use case for a switch that has more cases than values in the switch expression:
const std = @import("std");
fn encodeInteger(int_value: anytype) void {
switch (int_value) {
0...std.math.maxInt(u8) => std.debug.print("value: {}", .{int_value}),
std.math.maxInt(u8) + 1...std.math.maxInt(u16) => @compileError("branch analyzed"),
std.math.maxInt(u16) + 1...std.math.maxInt(u32) => @compileError("branch analyzed"),
std.math.maxInt(u32) + 1...std.math.maxInt(u64) => @compileError("branch analyzed"),
else => unreachable,
}
}
test "comptime unreachable ranged switch" {
_ = encodeInteger(@as(u3, 4));
}
Which currently provides the following compile error:
$ zig test test.zig
test.zig:5:28: error: type 'u3' cannot represent integer value '255'
0...std.math.maxInt(u8) => std.debug.print("value: {}", .{int_value}),
Do you think the test should compile?
The real code I have right now looks like this, and is based on the bits of the integer, but it might be easier to switch on the value of the integer instead. This is also sub-optimal, because small values should use the smallest possible encoding, regardless of how big the type used to store them is.
const format: Spec.Format = switch (@typeInfo(T).int.signedness) {
.unsigned => switch (@typeInfo(T).int.bits) {
0...7 => .{ .positive_fixint = .{ .value = value } },
8 => .{ .uint_8 = {} },
9...16 => .{ .uint_16 = {} },
17...32 => .{ .uint_32 = {} },
33...64 => .{ .uint_64 = {} },
else => unreachable,
},
.signed => switch (@typeInfo(T).int.bits) {
0...6 => blk: {
if (value >= 0) {
break :blk .{ .positive_fixint = .{ .value = @intCast(value) } };
} else if (value >= -32) {
break :blk .{ .negative_fixint = .{ .value = value } };
} else {
break :blk .{ .int_8 = {} };
}
},
7...8 => .{ .int_8 = {} },
9...16 => .{ .int_16 = {} },
17...32 => .{ .int_32 = {} },
33...64 => .{ .int_64 = {} },
else => unreachable,
},
};
I’m leaning towards no, because in the nominal case of exhaustive switching, it would damage readability if you could have over-exhaustive switches.