Error: value with comptime-only type 'comptime_int' depends on runtime control flow

Hello,

I’m very new to zig and Im just trying to learn.
I’m trying to write a deck of cards program.
But I’ve encountered an error message that I don’t understand

In particular, I’m trying to write a struct bound function that returns the card’s name as a string. The struct is as follows.

const Card = struct {
    suite: Suite,
    value: Value,
    pub fn name(self: Card) []u8 {
        const v = switch (self.value) {
            .number => |n| blk: {
                if (n == 10) {
                    break :blk 'X';
                } else {
                    break :blk n + '0';
                }
            },
            .face => |f| blk: {
                break :blk switch (f) {
                    .Jack => 'J',
                    .Queen => 'Q',
                    .King => 'K',
                    .Ace => 'A',
                };
            },
        };
        return v;
    }
};

And the error message is

src/main.zig:24:28: error: value with comptime-only type 'comptime_int' depends on runtime control flow
                break :blk switch (f) {
                           ^~~~~~
src/main.zig:15:31: note: runtime control flow here
        const v = switch (self.value) {
                          ~~~~^~~~~~

I don’t understand what is supposed to be a compile-time value here.

Also, It doesn’t seem that simple to just cast an int to a string or u8

Thank you

Welcome to Zig as well as the forum!

Can you share more of your code? Specifically the definitions for Suite and Value

// No type in declaration. The compiler will choose a fitting type for you.
//     ↓
const v = switch...

All of your branches contain numbers (‘J’ for example is a number of type comptime_int representing the ascii code of J)
So zig assumes you wanted:

const v: comptime_int = switch...

But a comptime_int must be known at compile-time, thus an error is caused.

To fix this you can simply explicitly set the type:

const v: u8 = switch...

Hi :wave:

Here you go:

const Suite = enum { Spades, Clubs, Harts, Diomands };
const Face = enum { Jack, Queen, King, Ace };

const Value = union(enum) {
    number: u8,
    face: Face,
};

Thank you for the explanation, thats sorted it

Although the problem is solved, for the purpose of learning a bit more about Zig, I propose this example for this problem:

const std = @import("std");

const Suit = enum {
    Clubs,
    Diamonds,
    Hearts,
    Spades,
};

const Face = enum(u8) {
    Ace = 1,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King,
};

const Card = struct {
    face: Face,
    suit: Suit,

    pub fn format(self: Card, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
        _ = try writer.print("{s} of {s} with value {}", .{
            @tagName(self.face),
            @tagName(self.suit),
            @intFromEnum(self.face),
        });
    }
};

pub fn main() void {
    const aos = Card{ .face = .Ace, .suit = .Spades };
    std.debug.print("{}\n", .{aos});

    const qoh = Card{ .face = .Queen, .suit = .Hearts };
    std.debug.print("{}\n", .{qoh});
}

output:

Ace of Spades with value 1
Queen of Hearts with value 12
3 Likes

since your here can i ask one more thing

How can I loop over the possibilities for an enum?
I want to be able to iterate through the possible values of cards in order to create a deck, but

for (Face) |face| {
    _ = face;
}

is not valid zig. ( Type ‘type’ is not indexble )

1 Like

@typeInfo(Type).Enum.fields will give you a list of all the possible values of an enum. There’s a shortcut: std.meta.fields(Type).

2 Likes

As @LucasSantos says, you can loop over the enum fields with std.meta.fields but I believe it has to be an inline for like this:

inline for (std.meta.fields(Face)) |face| {
    // do something with face
}

The reason for this is that your dealing with types directly, and that can only be done at comptime. inline for is a for loop that runs at comptime.

2 Likes