-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Zig Version
0.14.0
Steps to Reproduce and Observed Behavior
Hi, it seems that std.MultiArrayList
hits the comptime branch quota once the underlying struct gets to 18 or so fields, but I am having some trouble finding the correct placement of @setEvalBranchQuota
in client code that will raise the limit.
Here is a repro case that will fail to compile:
const std = @import("std");
const Foo = struct {
a01: u32,
a02: u32,
a03: u32,
a04: u32,
a05: u32,
a06: u32,
a07: u32,
a08: u32,
a09: u32,
a10: u32,
a11: u32,
a12: u32,
a13: u32,
a14: u32,
a15: u32,
a16: u32,
a17: u32,
};
pub fn main() !void {
var gpa: std.heap.DebugAllocator(.{}) = .init;
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var list: std.MultiArrayList(Foo) = .empty;
defer list.deinit(allocator);
try list.resize(allocator, 1);
list.slice().items(.a01)[0] = 42;
}
Here is the output on godbolt for 0.14 (seemingly regardless of where I place @setEvalBranchQuota
):
/opt/compiler-explorer/zig-0.14.0/lib/std/math/log2.zig:24:13: error: evaluation exceeded 1000 backwards branches
while (x_shifted >> (shift_amt << 1) != 0) shift_amt <<= 1;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/zig-0.14.0/lib/std/math/log2.zig:24:13: note: use @setEvalBranchQuota() to raise the branch limit from 1000
/opt/compiler-explorer/zig-0.14.0/lib/std/math.zig:779:22: note: called from here
const base = log2(largest_positive_integer);
~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/zig-0.14.0/lib/std/meta.zig:546:49: note: called from here
.tag_type = std.math.IntFittingRange(0, field_infos.len - 1),
~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/zig-0.14.0/lib/std/meta.zig:386:61: note: called from here
pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) {
~~~~~~~~~^~~
/opt/compiler-explorer/zig-0.14.0/lib/std/multi_array_list.zig:568:34: note: called from here
return meta.fieldInfo(Elem, field).type;
~~~~~~~~~~~~~~^~~~~~~~~~~~~
/opt/compiler-explorer/zig-0.14.0/lib/std/multi_array_list.zig:83:73: note: called from here
pub fn items(self: Slice, comptime field: Field) []FieldType(field) {
~~~~~~~~~^~~~~~~
/opt/compiler-explorer/zig-0.14.0/lib/std/multi_array_list.zig:463:71: note: called from here
@memcpy(other_slice.items(field), self_slice.items(field));
~~~~~~~~~~~~~~~~^~~~~~~
referenced by:
ensureTotalCapacity: /opt/compiler-explorer/zig-0.14.0/lib/std/multi_array_list.zig:411:36
resize: /opt/compiler-explorer/zig-0.14.0/lib/std/multi_array_list.zig:339:41
As a local workaround, I have modified std.MultiArrayList.FieldType
to use @FieldType(Elem, @tagName(field))
as its implemention (instead of stuff from std.meta
), as this reduces the comptime branch usage a lot and allows this repro case to compile.
However, I am confused how client code could raise the quota for this case so would like to raise it as an issue. I also wonder if std.MultiArrayList
or the std.meta
functions it relies on are missing some internal @setBranchEvalQuota
based on the number of fields of the struct so that it scales to any struct type? (See comments at https://ziggit.dev/t/placement-of-setevalbranchquota/9231/3)
Expected Behavior
It should be possible to use std.MultiArrayList
with larger structs without modification to the standard library.