zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

blob 556a8c99 (21035B) - Raw


      1 const std = @import("std");
      2 const builtin = @import("builtin");
      3 const Type = std.builtin.Type;
      4 const testing = std.testing;
      5 
      6 fn testTypes(comptime types: []const type) !void {
      7     inline for (types) |testType| {
      8         try testing.expect(testType == @Type(@typeInfo(testType)));
      9     }
     10 }
     11 
     12 test "Type.MetaType" {
     13     try testing.expect(type == @Type(.{ .Type = {} }));
     14     try testTypes(&[_]type{type});
     15 }
     16 
     17 test "Type.Void" {
     18     try testing.expect(void == @Type(.{ .Void = {} }));
     19     try testTypes(&[_]type{void});
     20 }
     21 
     22 test "Type.Bool" {
     23     try testing.expect(bool == @Type(.{ .Bool = {} }));
     24     try testTypes(&[_]type{bool});
     25 }
     26 
     27 test "Type.NoReturn" {
     28     try testing.expect(noreturn == @Type(.{ .NoReturn = {} }));
     29     try testTypes(&[_]type{noreturn});
     30 }
     31 
     32 test "Type.Int" {
     33     try testing.expect(u1 == @Type(.{ .Int = .{ .signedness = .unsigned, .bits = 1 } }));
     34     try testing.expect(i1 == @Type(.{ .Int = .{ .signedness = .signed, .bits = 1 } }));
     35     try testing.expect(u8 == @Type(.{ .Int = .{ .signedness = .unsigned, .bits = 8 } }));
     36     try testing.expect(i8 == @Type(.{ .Int = .{ .signedness = .signed, .bits = 8 } }));
     37     try testing.expect(u64 == @Type(.{ .Int = .{ .signedness = .unsigned, .bits = 64 } }));
     38     try testing.expect(i64 == @Type(.{ .Int = .{ .signedness = .signed, .bits = 64 } }));
     39     try testTypes(&[_]type{ u8, u32, i64 });
     40 }
     41 
     42 test "Type.ComptimeFloat" {
     43     try testTypes(&[_]type{comptime_float});
     44 }
     45 test "Type.ComptimeInt" {
     46     try testTypes(&[_]type{comptime_int});
     47 }
     48 test "Type.Undefined" {
     49     try testTypes(&[_]type{@TypeOf(undefined)});
     50 }
     51 test "Type.Null" {
     52     try testTypes(&[_]type{@TypeOf(null)});
     53 }
     54 
     55 test "Type.EnumLiteral" {
     56     try testTypes(&[_]type{
     57         @TypeOf(.Dummy),
     58     });
     59 }
     60 
     61 test "Type.Pointer" {
     62     try testTypes(&[_]type{
     63         // One Value Pointer Types
     64         *u8,                               *const u8,
     65         *volatile u8,                      *const volatile u8,
     66         *align(4) u8,                      *align(4) const u8,
     67         *align(4) volatile u8,             *align(4) const volatile u8,
     68         *align(8) u8,                      *align(8) const u8,
     69         *align(8) volatile u8,             *align(8) const volatile u8,
     70         *allowzero u8,                     *allowzero const u8,
     71         *allowzero volatile u8,            *allowzero const volatile u8,
     72         *allowzero align(4) u8,            *allowzero align(4) const u8,
     73         *allowzero align(4) volatile u8,   *allowzero align(4) const volatile u8,
     74         // Many Values Pointer Types
     75         [*]u8,                             [*]const u8,
     76         [*]volatile u8,                    [*]const volatile u8,
     77         [*]align(4) u8,                    [*]align(4) const u8,
     78         [*]align(4) volatile u8,           [*]align(4) const volatile u8,
     79         [*]align(8) u8,                    [*]align(8) const u8,
     80         [*]align(8) volatile u8,           [*]align(8) const volatile u8,
     81         [*]allowzero u8,                   [*]allowzero const u8,
     82         [*]allowzero volatile u8,          [*]allowzero const volatile u8,
     83         [*]allowzero align(4) u8,          [*]allowzero align(4) const u8,
     84         [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
     85         // Slice Types
     86         []u8,                              []const u8,
     87         []volatile u8,                     []const volatile u8,
     88         []align(4) u8,                     []align(4) const u8,
     89         []align(4) volatile u8,            []align(4) const volatile u8,
     90         []align(8) u8,                     []align(8) const u8,
     91         []align(8) volatile u8,            []align(8) const volatile u8,
     92         []allowzero u8,                    []allowzero const u8,
     93         []allowzero volatile u8,           []allowzero const volatile u8,
     94         []allowzero align(4) u8,           []allowzero align(4) const u8,
     95         []allowzero align(4) volatile u8,  []allowzero align(4) const volatile u8,
     96         // C Pointer Types
     97         [*c]u8,                            [*c]const u8,
     98         [*c]volatile u8,                   [*c]const volatile u8,
     99         [*c]align(4) u8,                   [*c]align(4) const u8,
    100         [*c]align(4) volatile u8,          [*c]align(4) const volatile u8,
    101         [*c]align(8) u8,                   [*c]align(8) const u8,
    102         [*c]align(8) volatile u8,          [*c]align(8) const volatile u8,
    103     });
    104 }
    105 
    106 test "Type.Float" {
    107     try testing.expect(f16 == @Type(.{ .Float = .{ .bits = 16 } }));
    108     try testing.expect(f32 == @Type(.{ .Float = .{ .bits = 32 } }));
    109     try testing.expect(f64 == @Type(.{ .Float = .{ .bits = 64 } }));
    110     try testing.expect(f80 == @Type(.{ .Float = .{ .bits = 80 } }));
    111     try testing.expect(f128 == @Type(.{ .Float = .{ .bits = 128 } }));
    112     try testTypes(&[_]type{ f16, f32, f64, f80, f128 });
    113 }
    114 
    115 test "Type.Array" {
    116     try testing.expect([123]u8 == @Type(.{
    117         .Array = .{
    118             .len = 123,
    119             .child = u8,
    120             .sentinel = null,
    121         },
    122     }));
    123     try testing.expect([2]u32 == @Type(.{
    124         .Array = .{
    125             .len = 2,
    126             .child = u32,
    127             .sentinel = null,
    128         },
    129     }));
    130     try testing.expect([2:0]u32 == @Type(.{
    131         .Array = .{
    132             .len = 2,
    133             .child = u32,
    134             .sentinel = &@as(u32, 0),
    135         },
    136     }));
    137     try testTypes(&[_]type{ [1]u8, [30]usize, [7]bool });
    138 }
    139 
    140 test "@Type create slice with null sentinel" {
    141     const Slice = @Type(.{
    142         .Pointer = .{
    143             .size = .Slice,
    144             .is_const = true,
    145             .is_volatile = false,
    146             .is_allowzero = false,
    147             .alignment = 8,
    148             .address_space = .generic,
    149             .child = *i32,
    150             .sentinel = null,
    151         },
    152     });
    153     try testing.expect(Slice == []align(8) const *i32);
    154 }
    155 
    156 test "@Type picks up the sentinel value from Type" {
    157     try testTypes(&[_]type{
    158         [11:0]u8,                            [4:10]u8,
    159         [*:0]u8,                             [*:0]const u8,
    160         [*:0]volatile u8,                    [*:0]const volatile u8,
    161         [*:0]align(4) u8,                    [*:0]align(4) const u8,
    162         [*:0]align(4) volatile u8,           [*:0]align(4) const volatile u8,
    163         [*:0]align(8) u8,                    [*:0]align(8) const u8,
    164         [*:0]align(8) volatile u8,           [*:0]align(8) const volatile u8,
    165         [*:0]allowzero u8,                   [*:0]allowzero const u8,
    166         [*:0]allowzero volatile u8,          [*:0]allowzero const volatile u8,
    167         [*:0]allowzero align(4) u8,          [*:0]allowzero align(4) const u8,
    168         [*:0]allowzero align(4) volatile u8, [*:0]allowzero align(4) const volatile u8,
    169         [*:5]allowzero align(4) volatile u8, [*:5]allowzero align(4) const volatile u8,
    170         [:0]u8,                              [:0]const u8,
    171         [:0]volatile u8,                     [:0]const volatile u8,
    172         [:0]align(4) u8,                     [:0]align(4) const u8,
    173         [:0]align(4) volatile u8,            [:0]align(4) const volatile u8,
    174         [:0]align(8) u8,                     [:0]align(8) const u8,
    175         [:0]align(8) volatile u8,            [:0]align(8) const volatile u8,
    176         [:0]allowzero u8,                    [:0]allowzero const u8,
    177         [:0]allowzero volatile u8,           [:0]allowzero const volatile u8,
    178         [:0]allowzero align(4) u8,           [:0]allowzero align(4) const u8,
    179         [:0]allowzero align(4) volatile u8,  [:0]allowzero align(4) const volatile u8,
    180         [:4]allowzero align(4) volatile u8,  [:4]allowzero align(4) const volatile u8,
    181     });
    182 }
    183 
    184 test "Type.Optional" {
    185     try testTypes(&[_]type{
    186         ?u8,
    187         ?*u8,
    188         ?[]u8,
    189         ?[*]u8,
    190         ?[*c]u8,
    191     });
    192 }
    193 
    194 test "Type.ErrorUnion" {
    195     try testTypes(&[_]type{
    196         error{}!void,
    197         error{Error}!void,
    198     });
    199 }
    200 
    201 test "Type.Opaque" {
    202     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
    203     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
    204     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    205     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    206 
    207     const Opaque = @Type(.{
    208         .Opaque = .{
    209             .decls = &.{},
    210         },
    211     });
    212     try testing.expect(Opaque != opaque {});
    213     try testing.expectEqualSlices(
    214         Type.Declaration,
    215         &.{},
    216         @typeInfo(Opaque).Opaque.decls,
    217     );
    218 }
    219 
    220 test "Type.Vector" {
    221     try testTypes(&[_]type{
    222         @Vector(0, u8),
    223         @Vector(4, u8),
    224         @Vector(8, *u8),
    225         @Vector(0, u8),
    226         @Vector(4, u8),
    227         @Vector(8, *u8),
    228     });
    229 }
    230 
    231 test "Type.AnyFrame" {
    232     if (builtin.zig_backend != .stage1) {
    233         // https://github.com/ziglang/zig/issues/6025
    234         return error.SkipZigTest;
    235     }
    236 
    237     try testTypes(&[_]type{
    238         anyframe,
    239         anyframe->u8,
    240         anyframe->anyframe->u8,
    241     });
    242 }
    243 
    244 fn add(a: i32, b: i32) i32 {
    245     return a + b;
    246 }
    247 
    248 test "Type.ErrorSet" {
    249     if (builtin.zig_backend == .stage1) return error.SkipZigTest;
    250 
    251     try testing.expect(@Type(.{ .ErrorSet = null }) == anyerror);
    252 
    253     // error sets don't compare equal so just check if they compile
    254     inline for (.{ error{}, error{A}, error{ A, B, C } }) |T| {
    255         const info = @typeInfo(T);
    256         const T2 = @Type(info);
    257         try testing.expect(T == T2);
    258     }
    259 }
    260 
    261 test "Type.Struct" {
    262     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
    263     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
    264     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    265     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    266 
    267     const A = @Type(@typeInfo(struct { x: u8, y: u32 }));
    268     const infoA = @typeInfo(A).Struct;
    269     try testing.expectEqual(Type.ContainerLayout.Auto, infoA.layout);
    270     try testing.expectEqualSlices(u8, "x", infoA.fields[0].name);
    271     try testing.expectEqual(u8, infoA.fields[0].field_type);
    272     try testing.expectEqual(@as(?*const anyopaque, null), infoA.fields[0].default_value);
    273     try testing.expectEqualSlices(u8, "y", infoA.fields[1].name);
    274     try testing.expectEqual(u32, infoA.fields[1].field_type);
    275     try testing.expectEqual(@as(?*const anyopaque, null), infoA.fields[1].default_value);
    276     try testing.expectEqualSlices(Type.Declaration, &.{}, infoA.decls);
    277     try testing.expectEqual(@as(bool, false), infoA.is_tuple);
    278 
    279     var a = A{ .x = 0, .y = 1 };
    280     try testing.expectEqual(@as(u8, 0), a.x);
    281     try testing.expectEqual(@as(u32, 1), a.y);
    282     a.y += 1;
    283     try testing.expectEqual(@as(u32, 2), a.y);
    284 
    285     const B = @Type(@typeInfo(extern struct { x: u8, y: u32 = 5 }));
    286     const infoB = @typeInfo(B).Struct;
    287     try testing.expectEqual(Type.ContainerLayout.Extern, infoB.layout);
    288     try testing.expectEqualSlices(u8, "x", infoB.fields[0].name);
    289     try testing.expectEqual(u8, infoB.fields[0].field_type);
    290     try testing.expectEqual(@as(?*const anyopaque, null), infoB.fields[0].default_value);
    291     try testing.expectEqualSlices(u8, "y", infoB.fields[1].name);
    292     try testing.expectEqual(u32, infoB.fields[1].field_type);
    293     try testing.expectEqual(@as(u32, 5), @ptrCast(*align(1) const u32, infoB.fields[1].default_value.?).*);
    294     try testing.expectEqual(@as(usize, 0), infoB.decls.len);
    295     try testing.expectEqual(@as(bool, false), infoB.is_tuple);
    296 
    297     const C = @Type(@typeInfo(packed struct { x: u8 = 3, y: u32 = 5 }));
    298     const infoC = @typeInfo(C).Struct;
    299     try testing.expectEqual(Type.ContainerLayout.Packed, infoC.layout);
    300     try testing.expectEqualSlices(u8, "x", infoC.fields[0].name);
    301     try testing.expectEqual(u8, infoC.fields[0].field_type);
    302     try testing.expectEqual(@as(u8, 3), @ptrCast(*const u8, infoC.fields[0].default_value.?).*);
    303     try testing.expectEqualSlices(u8, "y", infoC.fields[1].name);
    304     try testing.expectEqual(u32, infoC.fields[1].field_type);
    305     try testing.expectEqual(@as(u32, 5), @ptrCast(*align(1) const u32, infoC.fields[1].default_value.?).*);
    306     try testing.expectEqual(@as(usize, 0), infoC.decls.len);
    307     try testing.expectEqual(@as(bool, false), infoC.is_tuple);
    308 
    309     // anon structs
    310     const D = @Type(@typeInfo(@TypeOf(.{ .x = 3, .y = 5 })));
    311     const infoD = @typeInfo(D).Struct;
    312     try testing.expectEqual(Type.ContainerLayout.Auto, infoD.layout);
    313     try testing.expectEqualSlices(u8, "x", infoD.fields[0].name);
    314     try testing.expectEqual(comptime_int, infoD.fields[0].field_type);
    315     try testing.expectEqual(@as(comptime_int, 3), @ptrCast(*const comptime_int, infoD.fields[0].default_value.?).*);
    316     try testing.expectEqualSlices(u8, "y", infoD.fields[1].name);
    317     try testing.expectEqual(comptime_int, infoD.fields[1].field_type);
    318     try testing.expectEqual(@as(comptime_int, 5), @ptrCast(*const comptime_int, infoD.fields[1].default_value.?).*);
    319     try testing.expectEqual(@as(usize, 0), infoD.decls.len);
    320     try testing.expectEqual(@as(bool, false), infoD.is_tuple);
    321 
    322     // tuples
    323     const E = @Type(@typeInfo(@TypeOf(.{ 1, 2 })));
    324     const infoE = @typeInfo(E).Struct;
    325     try testing.expectEqual(Type.ContainerLayout.Auto, infoE.layout);
    326     try testing.expectEqualSlices(u8, "0", infoE.fields[0].name);
    327     try testing.expectEqual(comptime_int, infoE.fields[0].field_type);
    328     try testing.expectEqual(@as(comptime_int, 1), @ptrCast(*const comptime_int, infoE.fields[0].default_value.?).*);
    329     try testing.expectEqualSlices(u8, "1", infoE.fields[1].name);
    330     try testing.expectEqual(comptime_int, infoE.fields[1].field_type);
    331     try testing.expectEqual(@as(comptime_int, 2), @ptrCast(*const comptime_int, infoE.fields[1].default_value.?).*);
    332     try testing.expectEqual(@as(usize, 0), infoE.decls.len);
    333     try testing.expectEqual(@as(bool, true), infoE.is_tuple);
    334 
    335     // empty struct
    336     const F = @Type(@typeInfo(struct {}));
    337     const infoF = @typeInfo(F).Struct;
    338     try testing.expectEqual(Type.ContainerLayout.Auto, infoF.layout);
    339     try testing.expect(infoF.fields.len == 0);
    340     try testing.expectEqual(@as(bool, false), infoF.is_tuple);
    341 
    342     // empty tuple
    343     const G = @Type(@typeInfo(@TypeOf(.{})));
    344     const infoG = @typeInfo(G).Struct;
    345     try testing.expectEqual(Type.ContainerLayout.Auto, infoG.layout);
    346     try testing.expect(infoG.fields.len == 0);
    347     try testing.expectEqual(@as(bool, true), infoG.is_tuple);
    348 }
    349 
    350 test "Type.Enum" {
    351     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
    352     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    353     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    354 
    355     const Foo = @Type(.{
    356         .Enum = .{
    357             .layout = .Auto,
    358             .tag_type = u8,
    359             .fields = &.{
    360                 .{ .name = "a", .value = 1 },
    361                 .{ .name = "b", .value = 5 },
    362             },
    363             .decls = &.{},
    364             .is_exhaustive = true,
    365         },
    366     });
    367     try testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
    368     try testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
    369     try testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
    370     const Bar = @Type(.{
    371         .Enum = .{
    372             // stage2 only has auto layouts
    373             .layout = if (builtin.zig_backend == .stage1)
    374                 .Extern
    375             else
    376                 .Auto,
    377 
    378             .tag_type = u32,
    379             .fields = &.{
    380                 .{ .name = "a", .value = 1 },
    381                 .{ .name = "b", .value = 5 },
    382             },
    383             .decls = &.{},
    384             .is_exhaustive = false,
    385         },
    386     });
    387     try testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
    388     try testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
    389     try testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
    390     try testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
    391 }
    392 
    393 test "Type.Union" {
    394     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
    395     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
    396     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
    397     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
    398 
    399     const Untagged = @Type(.{
    400         .Union = .{
    401             .layout = .Extern,
    402             .tag_type = null,
    403             .fields = &.{
    404                 .{ .name = "int", .field_type = i32, .alignment = @alignOf(f32) },
    405                 .{ .name = "float", .field_type = f32, .alignment = @alignOf(f32) },
    406             },
    407             .decls = &.{},
    408         },
    409     });
    410     var untagged = Untagged{ .int = 1 };
    411     untagged.float = 2.0;
    412     untagged.int = 3;
    413     try testing.expectEqual(@as(i32, 3), untagged.int);
    414 
    415     const PackedUntagged = @Type(.{
    416         .Union = .{
    417             .layout = .Packed,
    418             .tag_type = null,
    419             .fields = &.{
    420                 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
    421                 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
    422             },
    423             .decls = &.{},
    424         },
    425     });
    426     var packed_untagged = PackedUntagged{ .signed = -1 };
    427     try testing.expectEqual(@as(i32, -1), packed_untagged.signed);
    428     try testing.expectEqual(~@as(u32, 0), packed_untagged.unsigned);
    429 
    430     const Tag = @Type(.{
    431         .Enum = .{
    432             .layout = .Auto,
    433             .tag_type = u1,
    434             .fields = &.{
    435                 .{ .name = "signed", .value = 0 },
    436                 .{ .name = "unsigned", .value = 1 },
    437             },
    438             .decls = &.{},
    439             .is_exhaustive = true,
    440         },
    441     });
    442     const Tagged = @Type(.{
    443         .Union = .{
    444             .layout = .Auto,
    445             .tag_type = Tag,
    446             .fields = &.{
    447                 .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) },
    448                 .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) },
    449             },
    450             .decls = &.{},
    451         },
    452     });
    453     var tagged = Tagged{ .signed = -1 };
    454     try testing.expectEqual(Tag.signed, tagged);
    455     tagged = .{ .unsigned = 1 };
    456     try testing.expectEqual(Tag.unsigned, tagged);
    457 }
    458 
    459 test "Type.Union from Type.Enum" {
    460     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
    461 
    462     const Tag = @Type(.{
    463         .Enum = .{
    464             .layout = .Auto,
    465             .tag_type = u0,
    466             .fields = &.{
    467                 .{ .name = "working_as_expected", .value = 0 },
    468             },
    469             .decls = &.{},
    470             .is_exhaustive = true,
    471         },
    472     });
    473     const T = @Type(.{
    474         .Union = .{
    475             .layout = .Auto,
    476             .tag_type = Tag,
    477             .fields = &.{
    478                 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
    479             },
    480             .decls = &.{},
    481         },
    482     });
    483     _ = @typeInfo(T).Union;
    484 }
    485 
    486 test "Type.Union from regular enum" {
    487     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
    488 
    489     const E = enum { working_as_expected };
    490     const T = @Type(.{
    491         .Union = .{
    492             .layout = .Auto,
    493             .tag_type = E,
    494             .fields = &.{
    495                 .{ .name = "working_as_expected", .field_type = u32, .alignment = @alignOf(u32) },
    496             },
    497             .decls = &.{},
    498         },
    499     });
    500     _ = @typeInfo(T).Union;
    501 }
    502 
    503 test "Type.Fn" {
    504     if (builtin.zig_backend == .stage1) return error.SkipZigTest;
    505 
    506     if (true) {
    507         // https://github.com/ziglang/zig/issues/12360
    508         return error.SkipZigTest;
    509     }
    510 
    511     const some_opaque = opaque {};
    512     const some_ptr = *some_opaque;
    513     const T = fn (c_int, some_ptr) callconv(.C) void;
    514 
    515     {
    516         const fn_info = std.builtin.Type{ .Fn = .{
    517             .calling_convention = .C,
    518             .alignment = 0,
    519             .is_generic = false,
    520             .is_var_args = false,
    521             .return_type = void,
    522             .args = &.{
    523                 .{ .is_generic = false, .is_noalias = false, .arg_type = c_int },
    524                 .{ .is_generic = false, .is_noalias = false, .arg_type = some_ptr },
    525             },
    526         } };
    527 
    528         const fn_type = @Type(fn_info);
    529         try std.testing.expectEqual(T, fn_type);
    530     }
    531 
    532     {
    533         const fn_info = @typeInfo(T);
    534         const fn_type = @Type(fn_info);
    535         try std.testing.expectEqual(T, fn_type);
    536     }
    537 }
    538 
    539 test "reified struct field name from optional payload" {
    540     comptime {
    541         const m_name: ?[1]u8 = "a".*;
    542         if (m_name) |*name| {
    543             const T = @Type(.{ .Struct = .{
    544                 .layout = .Auto,
    545                 .fields = &.{.{
    546                     .name = name,
    547                     .field_type = u8,
    548                     .default_value = null,
    549                     .is_comptime = false,
    550                     .alignment = 1,
    551                 }},
    552                 .decls = &.{},
    553                 .is_tuple = false,
    554             } });
    555             var t: T = .{ .a = 123 };
    556             try std.testing.expect(t.a == 123);
    557         }
    558     }
    559 }