Why can't container level mutable variables be comptime?

The following code compiles. But if the n declaration is not local, then it fails to compile.

const std = @import("std");

//comptime var n: comptime_int = 0; // error

pub fn main() void {
    comptime var n: comptime_int = 0; // okay
    
    n += 1;
    std.debug.print("{}\n", .{ n });
    n += 1;
    std.debug.print("{}\n", .{ n });
}

Here’s an earlier answer:

3 Likes

if global mutable comptime state existed your code could depend on the order zig evaluates things, a small refactor could drastically change the output of your program (assuming the output depends on the comptime state)

4 Likes

Okay, my intention is to wrap the comptime logic in a function call. Finally, I found a way:

const std = @import("std");

const feb = struct {
    // comptime n: comptime_int = 0, // a BTW question, why doesn't this work?

    n: comptime_int = 0,
    
    fn next(self: *@This()) comptime_int {
        defer self.n += 1;
        return self.n;
    }
};

pub fn main() void {
    comptime var f: feb = .{};
    std.debug.print("{}\n", .{ f.next() });
    std.debug.print("{}\n", .{ f.next() });
    std.debug.print("{}\n", .{ f.next() });
    std.debug.print("{}\n", .{ f.next() });
}

Yeah, a field with a comptime only type makes the struct comptime only, and a comptime only return type makes the function implicitly comptime.

Note that even if all the function inputs are comptime only, or annotated with comptime, if the return type can be runtime then the function will not implicitly run at comptime.

2 Likes