Runtime value contains reference to comptime var

I am trying to write some code that calls a method on members of a tuple. But I keep getting the compile error “runtime value contains reference to comptime var”.

My points of confusion are:

  1. I wrote a similar test case that uses integers instead of structs as the tuple members and this test case works just fine.
  2. I have annotated all types explicitly and there is no “comptime” anywhere that I can see.

This is the code:

const std = @import("std");

test "works" {
    var t: struct { i32, i32 } = .{ 1, 2 };
    var result: struct { i32, i32 } = undefined;

    inline for (0..t.len) |i| {
        t[i] += 1;
        result[i] = t[i];
    }

    try std.testing.expectEqual(.{ 2, 3 }, t);
    try std.testing.expectEqual(.{ 2, 3 }, result);
}

test "broken" {
    const I = struct {
        fn next(_: *const @This()) i32 {
            return 2;
        }
    };

    var iters: struct { I, I } = .{ I{}, I{} };
    //@compileError(@typeName(@TypeOf(iters)));

    var result: struct { i32, i32 } = undefined;

    //inline for (0..iters.len) |i| {
    //    result[i] = iters[i].next(); // Same error as below
    //}

    result[0] = iters[0].next(); // error: runtime value contains reference to comptime var
    result[1] = iters[1].next();

    try std.testing.expectEqual(result, .{ 2, 2 });
}

When I print the type of iters it reports:

src/main.zig:28:5: error: struct { comptime main.test.broken.I = .{}, comptime main.test.broken.I = .{} }
    @compileError(@typeName(@TypeOf(iters)));

So, is this a bug in the compiler? Because I explicitly specified the type of iters and in what I specified there is no comptime.

Is there any way that i can trick zig into accepting that the fields of the tuple are in fact not comptime?

I think this may have something to do with the fact that I has zero size.
If I put a field into I then it appears to work.

I guess some kind of optimization is making zero-sized structs always comptime known.
Either way I would say it is probably a compiler bug, since it’s causing problems despite the code being technically correct.

1 Like

As a workaround:

  • Declare iters as const instead of a var.
    and
  • Declare next as next(_: @This()).

Yes, there is a bug in the compiler, as @IntegratedQuantum already said.