Trying to use a two dimensional array as a a two dimensional slice

Consider that a slice is simply a pointer and a length. There’s not really anything that special about it besides syntax. If two dimensional slices are a thing that you want, you can just code them. Eg:

const std = @import("std");

fn DoubleSlice(constness: enum { @"var", @"const" }, T: type) type {
    const Pointer = switch (constness) {
        .@"var" => [*]T,
        .@"const" => [*]const T,
    };
    const Slice = switch (constness) {
        .@"var" => []T,
        .@"const" => []const T,
    };

    return struct {
        ptr: Pointer,
        size: [2]usize,

        fn get(ds: *const @This(), a: usize, b: usize) T {
            std.debug.assert(a < ds.size[0]);
            std.debug.assert(b < ds.size[1]);
            return ds.ptr[a * ds.size[0] + b];
        }

        fn getPtr(ds: *const @This(), a: usize, b: usize) *T {
            std.debug.assert(a < ds.size[0]);
            std.debug.assert(b < ds.size[1]);
            return &ds.ptr[a * ds.size[0] + b];
        }

        // arr should be a pointer to double array, or slice of arrays.
        fn init(arr: anytype) @This() {
            return .{
                .ptr = @ptrCast(arr.ptr),
                .size = .{ arr.len, if (arr.len > 0) arr[0].len else 0 },
            };
        }

        fn rowIter(ds: *const @This()) Iterator {
            return .{
                .ptr = ds.ptr,
                .rows = ds.size[0],
                .row_length = ds.size[1],
            };
        }

        const Iterator = struct {
            ptr: Pointer,
            rows: usize,
            row_length: usize,

            fn next(iter: *Iterator) ?Slice {
                if (iter.rows == 0) {
                    return null;
                }
                const r = iter.ptr[0..iter.row_length];
                iter.ptr += iter.row_length;
                iter.rows -= 1;
                return r;
            }
        };
    };
}

fn sum(ds: DoubleSlice(.@"const", u32)) u32 {
    var iter = ds.rowIter();
    var r: u32 = 0;
    while (iter.next()) |row| {
        for (row) |cell| {
            r += cell;
        }
    }
    return r;
}

pub fn main() void {
    {
        const arr: [2][2]u32 = .{
            .{ 0, 1 },
            .{ 2, 3 },
        };
        const s = sum(.init(&arr));
        std.debug.print("2by2 sum: {d}\n", .{s});
    }
    {
        const slice: []const [4]u32 = &.{
            .{ 0, 1, 2, 3 },
            .{ 4, 5, 6, 7 },
            .{ 8, 9, 10, 11 },
        };
        const s = sum(.init(slice));
        std.debug.print("3by4 sum: {d}\n", .{s});
    }
}