In comptime metaprogramming, what's idiomatic way to include type name in @compileError?

I have the following snippet:

            const arg_worst_case = switch (field.type) {
                u32, u64, u128 => std.math.maxInt(field.type),
                else => {
                    @compileLog(field.type);
                    @compileError("array_print: unhandled type");
                }
            };

Is there a better way to do this?

EDIT: Found the answer before hitting enter, its @typeName and ++:

else => @compileError("array_print: unsupported type: " ++ @typeName(field.type)),
3 Likes

There is also

@compileError(std.fmt.comptimePrint("unsupported type: {s}", .{@typeName(field.type)}));

which is probably worse in this case but scales better to more detailed messages.

2 Likes

This is a tangent, but here’s a trick I found to print enum variants:

const SupportedOs = enum {
    windows,
    linux,
    macos,
    freebsd,
};
pub const supported_os = switch (builtin.os.tag) {
    .windows => SupportedOs.windows,
    .linux => SupportedOs.linux,
    .macos => SupportedOs.macos,
    .freebsd => SupportedOs.freebsd,
    else => @compileError(std.fmt.comptimePrint("{s} is not a supported OS!", .{
        name: for (@typeInfo(std.Target.Os.Tag).@"enum".fields) |field| {
            if (@intFromEnum(builtin.os.tag) == field.value) break :name field.name;
        },
    })),
};

You can use @tagName instead, or the {t} format specifier within print/format.

3 Likes
const SupportedOs = enum {
    windows,
    linux,
    macos,
    freebsd,
};
pub const supported_os = switch (builtin.os.tag) {
    .windows => SupportedOs.windows,
    .linux => SupportedOs.linux,
    .macos => SupportedOs.macos,
    .freebsd => SupportedOs.freebsd,
    else => |tag| @compileError(@tagName(tag) ++ " is not a supported OS!"),
};

or alternatively:

pub const supported_os = switch (builtin.os.tag) {
    .windows => SupportedOs.windows,
    .linux => SupportedOs.linux,
    .macos => SupportedOs.macos,
    .freebsd => SupportedOs.freebsd,
    else => |tag| @compileError(std.fmt.comptimePrint("{t} is not a supported OS!", .{tag})),
};
2 Likes

You and @Sze just blew my mind! I searched for hours trying to find this solution :sweat_smile: thank you so much!