Error about runtime function pointer

I need to dispatch to different Zig log functions, depending on a runtime log level defined by a third party. I decided to switch on the runtime value, assign a function pointer based on that value, then call the function.

fn libusbLogCb(ctx: *libusb.Context, level: libusb.LogLevel, msg: [*c]const u8) callconv(.C) void {
    _ = ctx;
    const zig_log_fn_ptr = *const fn (comptime []const u8, anytype) void;
    const log_fn: zig_log_fn_ptr = switch (level) {
        .err => scoped_log.err,
        .warn => scoped_log.warn,
        .info => scoped_log.info,
        .debug => scoped_log.debug,
    };
    log_fn("{s}", .{msg});
}

const scoped_log = std.log.scoped(.whatever);

Unfortunately it doesn’t work, and I don’t understand why.

error: value with comptime-only type '*const fn (comptime []const u8, anytype) void' depends on runtime control flow
        const log_fn: zig_log_fn = switch (level) {
                                   ^~~~~~
src/transport.zig:34:44: note: runtime control flow here
        const log_fn: zig_log_fn = switch (level) {
                                           ^~~~~
src/transport.zig:34:36: note: function is generic

Why is zig_log_fn_ptr a comptime-only type? Surely there must be some way to do this at runtime? Each switch arm returns a function pointer with the same signature.

And what’s the deal with the “function is generic” note? Which function? So what?

Alternative ways of achieving this are welcome, but I’d still like to understand why my original approach isn’t working.

You cannot get a runtime function pointer to a function with comptime parameters.

To fix this, you’d need to either make level a comptime parameter, or just call the function inside the switch without using a function pointer in the first place.

I feel stupid for not noticing that :stuck_out_tongue:
Thank you