zig icon indicating copy to clipboard operation
zig copied to clipboard

Regression with "Unable to evaluate constant expression" in len of fixed size arrays

Open Jarred-Sumner opened this issue 2 years ago • 4 comments

Zig Version

0.11.0-dev.2571+31738de28

Steps to Reproduce and Observed Behavior

Run zig build-exe repro.zig:

// repro.zig
const std = @import("std");
pub fn main() anyerror!void {
    var hasher = std.hash.Wyhash.init(0);
    var remain: []const u8 = "hello world!";
    var buf: [hasher.buf.len]u8 = undefined;
    std.debug.print("buf {s} {s}", .{ &buf, remain });
}
❯ zig build-exe repro.zig
/Users/jarred/Desktop/repro.zig:5:21: error: unable to evaluate comptime expression
    var buf: [hasher.buf.len]u8 = undefined;
              ~~~~~~^~~~
referenced by:
    comptime_0: /Users/jarred/zig/0.11.0-dev.2571+31738de28/files/lib/std/start.zig:66:50
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

hasher.buf.len is comptime known because it is a fixed size array and therefore can be determined by the type definition of the Wyhash struct's buf field.

pub const Wyhash = struct {
    state: WyhashStateless,

    buf: [32]u8,
       // ^
    buf_len: usize,
// ...

Similarly, this fails to compile:

pub const Wyhash = struct {
    buf: [32]u8 = undefined,
};
const std = @import("std");
pub fn main() anyerror!void {
    var remain: []const u8 = "hello world!";
    var hasher = Wyhash{};
    var buf: [hasher.buf.len]u8 = undefined;
    std.debug.print("buf {s} {s}", .{ &buf, remain });
}

Expected Behavior

Compile successfully

This worked until at least 0.11.0-dev.2371+a31450375, which means it is a regression.

Jarred-Sumner avatar Apr 14 '23 08:04 Jarred-Sumner

Probably caused by #14819

Vexu avatar Apr 14 '23 09:04 Vexu

Possibly related to #12240

ominitay avatar Apr 14 '23 14:04 ominitay

Yes caused by that and yes related to that - it happens when you have another layer of field access before len. Here's an example of code that didn't work (at top-level!) prior to the change:

const S = struct {
    arr: [5]u8 = undefined,
};
var x: S = .{};

comptime {
    _ = x.arr.len;
}

Because function-level comptime now works properly, the same issue manifests itself there.

mlugg avatar Apr 14 '23 16:04 mlugg

Workaround:

comptime {
    // broken
    _ = s.arr.len;
    // works
    _ = @typeInfo(std.meta.FieldType(@TypeOf(s), .arr)).Array.len;
}

Would love to see this fixed, rooting for #15287.

henrikolsen549 avatar Aug 25 '23 08:08 henrikolsen549