How can you generate constant data in 0.16.0

In zig 0.15.2, you could replicate the &.{ 1, 2, 3 } syntax with metaprogramming.

const a: []const usize = &.{100, 17};
std.debug.print("{any}\n", .{a});

const b: []const usize = &@Type(.{ .@"struct" = .{ 
    .layout = .auto,
    .backing_integer = null,
    .fields = &.{
        .{
            .name = "0",
            .type = comptime_int,
            .default_value_ptr = &100,
            .is_comptime = true,
            .alignment = 0,
        },
        .{
            .name = "1",
            .type = comptime_int,
            .default_value_ptr = &17,
            .is_comptime = true,
            .alignment = 0,
        },
    },
    .decls = &.{},
    .is_tuple = true,
}}){};
std.debug.print("{any}\n", .{b}); // This prints the same value

This can be used to generate constant data at compile time.

// This function generates a slice out of an integer. The length of the slice is
// equal to the bit length of the integer. At every position, the slice contains
// the value of the corresponding bit in the integer (e.g 32, 64, 128) if that
// bit is set, or 0 if the bit is not set. This function currently has no real
// world use and is only shown here as an example.
fn generateConstantData(value: anytype) []const u64 {
    const bits = @typeInfo(@TypeOf(value)).int.bits;

    var fields = [_]std.builtin.Type.StructField{ undefined } ** bits;

    for (0..bits) |i| {
        const bit: comptime_int = (value & (1 << i));

        var buf: [8]u8 = undefined;
        fields[i] = .{
            .name = try std.fmt.bufPrintZ(&buf, "{}", .{i}),
            .type = comptime_int,
            .default_value_ptr = &bit,
            .is_comptime = true,
            .alignment = 0,
        };
    }

    return &@Type(.{ .@"struct" = .{ 
        .layout = .auto,
        .backing_integer = null,
        .fields = &fields,
        .decls = &.{},
        .is_tuple = true,
    }}){};
}
const c: []const u64 = comptime generateConstantData(@as(u8, 223));
std.debug.print("{any}\n", .{c});

const d: []const u64 = &.{ 1, 2, 4, 8, 16, 0, 64, 128 };
std.debug.print("{any}\n", .{d});

std.debug.print("{}\n", .{std.mem.eql(u64, c, d)}); // true

Unfortunately, @Type was removed in 0.16.0 and I tried to replicate this with the new @Struct and @Tuple builtins, but neither of them worked. Is there any way to make this possible again?
Link to full code

I might not fully understand your use-case, but it seems like you just want to use arrays:

const std = @import("std");

fn generateConstantData(value: anytype) []const u64 {
    const bits = @typeInfo(@TypeOf(value)).int.bits;
    var buf: [bits]u64 = undefined;

    for (0..bits) |i| {
        buf[i] = value & (1 << i);
    }

    const final = buf;
    return &final;
}

pub fn main() void {
    const a: []const usize = &.{ 100, 17 };
    std.debug.print("{any}\n", .{a});

    const b: []const usize = comptime blk: {
        // this is overly verbose just to resemble the original example
        var buf: [2]usize = undefined;

        buf[0] = 100;
        buf[1] = 17;

        const final = buf;
        break :blk &final;
    };
    std.debug.print("{any}\n", .{b});

    std.debug.print("{}\n", .{std.mem.eql(u64, a, b)});

    const c: []const u64 = comptime generateConstantData(@as(u8, 223));
    std.debug.print("{any}\n", .{c});

    const d: []const u64 = &.{ 1, 2, 4, 8, 16, 0, 64, 128 };
    std.debug.print("{any}\n", .{d});

    std.debug.print("{}\n", .{std.mem.eql(u64, c, d)});
}

See Comptime-Mutable Memory Changes for the const final = buf part.

Side note: you can get rid of the comptime at the callsite if you change the generateConstantData function like so:

fn generateConstantData(comptime value: anytype) []const u64 {
    return comptime blk: {
        const bits = @typeInfo(@TypeOf(value)).int.bits;
        var buf: [bits]u64 = undefined;

        for (0..bits) |i| {
            buf[i] = value & (1 << i);
        }

        const final = buf;
        break :blk &final;
    };
}

Yeah this is bit weird. Most constants are already compile time known, and if you aren’t sure you can make compiler error if they aren’t by prepending a expression with comptime.