Skip to content

std.MultiArrayList field count limit #23352

@sjb3d

Description

@sjb3d

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorcontributor friendlyThis issue is limited in scope and/or knowledge of Zig internals.standard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions