Unable to resolve type in comptime?

I’m trying to get the type of archetype at an index and ran into this error.

inline fn archetype(self: *Self, comptime archetype_type: ArchetypeType) *@TypeOf(self.archetypes[archetype_type.value()]) {
   return &self.archetypes[archetype_type.value()];
}

inline fn typeOfArchetype(self: *Self, comptime archetype_type: ArchetypeType) type {
   return @TypeOf(self.archetypes[archetype_type.value()]);
}

// @TypeOf(self.archetype(entity_archetype).*)  ok
// self.typeOfArchetype(entity_archetype) error: unable to resolve comptime value

I was very surprised since both should be known at compile time, so to check things
I made a simpler example to check that the error was also there but it isn’t?

const Inner = struct {
    u8,
    u8,
};

const Outer = struct {
    inner: Inner = .{ 1, 1 },

    const Self = @This();

    inline fn getPtr(self: *Self, comptime index: usize) *@TypeOf(self.inner[index]) {
        return &self.inner[index];
    }

    inline fn getType(self: *Self, comptime index: usize) type {
        return @TypeOf(self.inner[index]);
    }
};

test "Does a simpler example compile" {
    var outer: Outer = .{};
    try std.testing.expect(@TypeOf(outer.getPtr(0).*) == outer.getType(0));
}

Here is an example where I get a compile error, both component_id and comptime_archetype are compile time known.

if (comptime self.typeOfArchetype(comptime_archetype).Components.bitset.isSet(component_id)) return error.EntityIsMissingComponent;
src/ecs.zig:630:38: error: unable to resolve comptime value
                    if (comptime self.typeOfArchetype(comptime_archetype).Components.bitset.isSet(component_id)) return error.EntityIsMissingComponent;
                                 ~~~~^~~~~~~~~~~~~~~~
src/ecs.zig:630:25: note: 'comptime' keyword forces comptime evaluation
                    if (comptime self.typeOfArchetype(comptime_archetype).Components.bitset.isSet(component_id)) return error.EntityIsMissingComponent;

What am I missing here?

What’s the definition of archetype_type.value()?

pub fn NonExhaustiveEnum(comptime T: type, comptime Unique: type) type {
    ok: {
        @"error": {
            switch (@typeInfo(T)) {
                .int => |info| if (info.signedness != .unsigned) break :@"error",
                else => break :@"error",
            }

            switch (@typeInfo(Unique)) {
                .@"opaque" => break :ok,
                else => break :@"error",
            }
        }

        @compileError("Unexpected type was given: " ++ @typeName(T) ++ ", expected an unsiged integer.");
    }

    return enum(T) {
        _,

        const Self = @This();
        const _unique = Unique;

        pub inline fn make(int: T) Self {
            return @enumFromInt(int);
        }

        pub inline fn value(@"enum": Self) T {
            return @intFromEnum(@"enum");
        }
    };
}

pub const ArchetypeType = NonExhaustiveEnum(u32, opaque {});

This makes your test fail:

var outer: Outer = .{};                           // vvvvvvvv
try std.testing.expect(@TypeOf(outer.getPtr(0).*) == comptime outer.getType(0));

The issue is that trying to comptime-access the runtime outer takes precedence over inlining the method.

Compilation fails before the function gets inlined, so the compiler never gets to the point where it “realizes” getType only requires comptime information.

Try removing the comptime at the call site in your application code.

Alternatively you could make self a comptime var when you instantiate it.

3 Likes

Thank you, that was the issue!

Thank you for the easy to debug minimal example. :slight_smile: