Programmatically creating an interface table for a set of implementation fxns

Okay, @biosbob, this actually works for the *const F - I do this by distinguishing between reification and initialization here and I do that through another indirection. In short, I don’t see a way to do it through direct reification, but if you can stomach assignments via an inline for then this should do it for you:

const std = @import("std");

const print = std.log.debug;

const Impl = struct {
    pub fn foo(x: u32) void {
        print("foo({d})", .{x});
    }
    pub fn bar() void {
        print("bar", .{});
    }
};

fn ItabType(T: type) type {
    comptime {
        const TI = @typeInfo(T);
    
        const decls = TI.Struct.decls;
    
        var fld_list: [decls.len]std.builtin.Type.StructField = undefined;
    
        for (decls, 0..) |decl, i| {
    
            const func = @field(T, decl.name);
            
            fld_list[i] = std.builtin.Type.StructField{
                .name = decl.name,
                .type = *const @TypeOf(func),
                .default_value = null,
                .is_comptime = false,
                .alignment = 0,
            };
        }
    
        const freeze = fld_list;
    
        return @Type(.{ .Struct = .{
            .layout = .auto,
            .fields = freeze[0..],
            .decls = &.{},
            .is_tuple = false,
            .backing_integer = null,
        }});
    }
}

pub fn initItab(comptime impl: type) ItabType(impl) {

    var itab: ItabType(impl) = undefined;

    inline for (comptime std.meta.declarations(impl)) |decl| {
        @field(itab, decl.name) = @field(impl, decl.name);
    }

    return itab;
}

pub fn main() void {
    const itab = initItab(Impl);
    itab.bar();
}

What’s even funnier here is that this also works using a comptime keyword on the init function itself:

pub fn main() void {
    const itab = comptime initItab(Impl);
    itab.bar();
}

So… maybe you can actually get both constraints satisfied at once here? Odd. I think someone should look a little deeper into the discrepancy here.

4 Likes