Search code examples
arrayscompiler-errorszig

Does the Zig compiler consider arrays with comptime variable lengths as possible zero length arrays?


I'm experimenting with n-dimensional arrays in Zig.

const expectEqual = std.testing.expectEqual;

fn NdArray(comptime n: comptime_int, comptime shape: [n]comptime_int) type {
    if (shape.len == 0) {
        // zero dimensional array, return the scalar type
        return u8;
    } else {
        return struct {
            // positive dimensional array, return an array of arrays one dimension lower
            data: [shape[0]]NdArray(n - 1, shape[1..].*)
        };
    }
}

test "NdArray test" {
    const expected = struct {
        data: [2]struct {
            data: [6]struct {
                data: [9]struct {
                    data: u8
                }
            }
        }
    };
    expectEqual(NdArray(3, [3]comptime_int{ 2, 6, 9 }), expected);
}

But I get a compile error:

11:25: error: accessing a zero length array is not allowed
            data: [shape[0]]NdArray(n - 1, shape[1..].*)
                        ^

I don't see any way for the compiler to reach line 11, when shape has zero length. Does the compiler just forbid indexing of shape, because it doesn't have length expressed by an integer literal?


Solution

  • More of an extended comment than an answer, I think as tuket says, this seems to be compiler related. I look forward to a better explanation than the one I'm about give =D

    It looks like like the struct child scopes (if such a thing applies here) are evaluated before the outer scope. It seems to work if you shift the shape[0] reference to the parent scope:

    fn NdArray(comptime n: comptime_int, comptime shape: [n]comptime_int) type {
        if (shape.len == 0) {
            // zero dimensional array, return the scalar type
            return u8;
        } else {
            var foo = shape[0];
            return struct {
            // positive dimensional array, return an array of arrays one dimension lower
                data: [foo]NdArray(n - 1, shape[1..].*)
            };
        }
    }
    

    Since your error will come from the final pass of this recursion, another option would be to rewrite it in a non-recursive way.