zig icon indicating copy to clipboard operation
zig copied to clipboard

Tuple mutation fails in `comptime` context

Open topolarity opened this issue 3 years ago • 6 comments

Zig Version

0.10.0-dev.3351+90f23e131

Steps to Reproduce

fn foo() void {
    var x: u32 = 1;
    var y = .{ x, x + 1 };
    y = .{ 3, 4 };
    if (y[0] != 3) unreachable;
    if (y[1] != 4) unreachable;
}

test {
    foo(); // OK on stage1 and stage2
    comptime foo(); // Encounters `unreachable` on stage1, compile error on stage2
}

Related: #11983

Expected Behavior

This function call should work the same at runtime and at comptime.

Actual Behavior

Stage 1:

./test.zig:5:20: error: reached unreachable code
    if (y[0] != 3) unreachable;
                   ^
./test.zig:11:17: note: called from here
    comptime foo();
                ^
./test.zig:9:6: note: called from here
test {
     ^

Stage 2:

test.zig:4:12: error: value stored in comptime field does not match the default value of the field
    y = .{ 3, 4 };
           ^
test.zig:11:17: note: called from here
    comptime foo();
             ~~~^~

topolarity avatar Jul 27 '22 18:07 topolarity

It's not obvious to me how to best fix this.

Tuple fields are all inferred to be comptime in a comptime context, but this ends up restricting the mutability of those fields.

I think the solution is to change how we infer "comptime-ness" of tuple fields in a comptime context. The alternative, allowing mutation of comptime fields, invites a lot of additional complications.

topolarity avatar Jul 27 '22 18:07 topolarity

What if we made all tuples fully immutable? Are there strong use cases for tuple mutability?

SpexGuy avatar Jul 27 '22 18:07 SpexGuy

Would that restriction be "upwardly" viral, so that tuples can't be put in any mutable container or be the target of a mutable pointer? Seems like that would mean some generics like std.ArrayList(std.meta.Tuple(&.{f32, f16})) would no longer work

topolarity avatar Jul 27 '22 18:07 topolarity

no it would be only as if it was a [N]const Ts a mutable list of const tuples would still be fine

nektro avatar Jul 27 '22 19:07 nektro

I think it would have to be upwardly viral in order to make any sense, since you can't overwrite it after it's been created no matter what. This would also mean that tuples can't get defined values after being heap allocated, which is a bit weird but not necessarily a problem IMO.

SpexGuy avatar Jul 27 '22 22:07 SpexGuy

What do you think of the alternative solution of treating var in a comptime context differently than comptime var?

The main idea would be that only explicitly comptime objects (i.e. comptime var, literals, comptime params, and const objects with explicitly comptime initializers) are treated as comptime for the purpose of type inference/semantics.

Meanwhile, a comptime context would not affect type inference - it is just emulation, so a var would always be "semantically runtime-known" despite being evaluated at compile-time.

topolarity avatar Jul 27 '22 23:07 topolarity