Allow labeling container-level `comptime blk: {}`

This code:

comptime blk: { // container-level one!
    if (@import("builtin").is_test) break :blk;
}

doesn’t compile:

:1:15: error: expected type expression, found '{'
comptime blk: { // container-level one!
              ^

While it can be worked around by adding an extra nested block, I suggest fixing Zig itself, so that such container-level comptime blocks were treated like non-container-level ones, which compile fine:

pub fn main() void {
    comptime blk: {
        if (@import("builtin").is_test) break :blk;
    }
}
1 Like

A work around could be doing as such:

const _ = blk: {
    if (@import("builtin").is_test) break :blk;
};

const _ = {...}; is problematic. For instance, when in the non-test mode, the following doesn’t export symbols as someone might suppose:

const _ = blk: {
    if (@import("builtin").is_test) break :blk;
    for (@typeInfo(@This()).@"struct".decls) |decl| {
        const field = @field(@This(), decl.name);
        if (@TypeOf(field) != @TypeOf(@field(c, decl.name)))
            @compileError("pub decl type mismatch: " ++ decl.name);
        @export(&field, .{ .name = decl.name, .linkage = .strong });
    }
};

whereas the equivalent container-level comptime {...} would export them.

If you want to run arbitrary comptime logic at container level just use a comptime {..} block, that is its purpose anyway.
The value of global’s (const or var or fn) are only evaluated when they are used, or exported.
Values with the type of void aren’t evaluated because they are always the same.

If for some reason, you want to make it work, just add export and a type and break with values. Seriously, just use comptime

to answer the actual question, the proper workaround would be to have your labelled block inside a comptime block

comptime {
    blk: {
        //...
    }
}
1 Like

Yes of course, and it’s exactly the workaround I meant by:


The actual question is a(n informal) proposal to make the language more regular with regards to comptime blocks. Learnt that a comptime block can be labeled, people will expect this mechanism to work everywhere, including container levels. Not being able to label there will be perceived as a defect of the Zig parser and/or a weird exception to the general rule one must remember separately, thus contradicting the Zen’s point:

  • Reduce the amount one must remember.

Your workaround is putting it in the body of a function,
what I suggested works outside a function.
But yes I agree labelled comptime blocks should work at the container level, and this might actually be a bug

If you’re about the fn main code fragment, that wasn’t the workaround. Just a demonstration of the labelability of local comptime blocks. Sorry if I didn’t put it clear enough.

That make sense, I was wondering why you would go to that as a workaround :3

1 Like