1const std = @import("std");
2const builtin = @import("builtin");
3const mem = std.mem;
4
5const Type = std.builtin.Type;
6const TypeId = std.builtin.TypeId;
7
8const assert = std.debug.assert;
9const expect = std.testing.expect;
10const expectEqualStrings = std.testing.expectEqualStrings;
11
12test "type info: integer, floating point type info" {
13 try testIntFloat();
14 try comptime testIntFloat();
15}
16
17fn testIntFloat() !void {
18 const u8_info = @typeInfo(u8);
19 try expect(u8_info == .int);
20 try expect(u8_info.int.signedness == .unsigned);
21 try expect(u8_info.int.bits == 8);
22
23 const f64_info = @typeInfo(f64);
24 try expect(f64_info == .float);
25 try expect(f64_info.float.bits == 64);
26}
27
28test "type info: optional type info" {
29 try testOptional();
30 try comptime testOptional();
31}
32
33fn testOptional() !void {
34 const null_info = @typeInfo(?void);
35 try expect(null_info == .optional);
36 try expect(null_info.optional.child == void);
37}
38
39test "type info: C pointer type info" {
40 try testCPtr();
41 try comptime testCPtr();
42}
43
44fn testCPtr() !void {
45 const ptr_info = @typeInfo([*c]align(4) const i8);
46 try expect(ptr_info == .pointer);
47 try expect(ptr_info.pointer.size == .c);
48 try expect(ptr_info.pointer.attrs.@"const");
49 try expect(!ptr_info.pointer.attrs.@"volatile");
50 try expect(ptr_info.pointer.attrs.@"align" == 4);
51 try expect(ptr_info.pointer.child == i8);
52}
53
54test "type info: value is correctly copied" {
55 comptime {
56 var ptrInfo = @typeInfo([]u32);
57 ptrInfo.pointer.size = .one;
58 try expect(@typeInfo([]u32).pointer.size == .slice);
59 }
60}
61
62test "type info: tag type, void info" {
63 try testBasic();
64 try comptime testBasic();
65}
66
67fn testBasic() !void {
68 try expect(@typeInfo(Type).@"union".tag_type == TypeId);
69 const void_info = @typeInfo(void);
70 try expect(void_info == TypeId.void);
71 try expect(void_info.void == {});
72}
73
74test "type info: pointer type info" {
75 try testPointer();
76 try comptime testPointer();
77}
78
79fn testPointer() !void {
80 const u32_ptr_info = @typeInfo(*u32);
81 try expect(u32_ptr_info == .pointer);
82 try expect(u32_ptr_info.pointer.size == .one);
83 try expect(u32_ptr_info.pointer.attrs.@"const" == false);
84 try expect(u32_ptr_info.pointer.attrs.@"volatile" == false);
85 try expect(u32_ptr_info.pointer.attrs.@"align" == null);
86 try expect(u32_ptr_info.pointer.child == u32);
87 try expect(u32_ptr_info.pointer.sentinel() == null);
88}
89
90test "type info: unknown length pointer type info" {
91 try testUnknownLenPtr();
92 try comptime testUnknownLenPtr();
93}
94
95fn testUnknownLenPtr() !void {
96 const u32_ptr_info = @typeInfo([*]const volatile f64);
97 try expect(u32_ptr_info == .pointer);
98 try expect(u32_ptr_info.pointer.size == .many);
99 try expect(u32_ptr_info.pointer.attrs.@"const" == true);
100 try expect(u32_ptr_info.pointer.attrs.@"volatile" == true);
101 try expect(u32_ptr_info.pointer.attrs.@"align" == null);
102 try expect(u32_ptr_info.pointer.child == f64);
103 try expect(u32_ptr_info.pointer.sentinel() == null);
104}
105
106test "type info: null terminated pointer type info" {
107 try testNullTerminatedPtr();
108 try comptime testNullTerminatedPtr();
109}
110
111fn testNullTerminatedPtr() !void {
112 const ptr_info = @typeInfo([*:0]u8);
113 try expect(ptr_info == .pointer);
114 try expect(ptr_info.pointer.size == .many);
115 try expect(ptr_info.pointer.attrs.@"const" == false);
116 try expect(ptr_info.pointer.attrs.@"volatile" == false);
117 try expect(ptr_info.pointer.sentinel().? == 0);
118
119 try expect(@typeInfo([:0]u8).pointer.sentinel() != null);
120}
121
122test "type info: slice type info" {
123 try testSlice();
124 try comptime testSlice();
125}
126
127fn testSlice() !void {
128 const u32_slice_info = @typeInfo([]u32);
129 try expect(u32_slice_info == .pointer);
130 try expect(u32_slice_info.pointer.size == .slice);
131 try expect(u32_slice_info.pointer.attrs.@"const" == false);
132 try expect(u32_slice_info.pointer.attrs.@"volatile" == false);
133 try expect(u32_slice_info.pointer.attrs.@"align" == null);
134 try expect(u32_slice_info.pointer.child == u32);
135}
136
137test "type info: array type info" {
138 try testArray();
139 try comptime testArray();
140}
141
142fn testArray() !void {
143 {
144 const info = @typeInfo([42]u8);
145 try expect(info == .array);
146 try expect(info.array.len == 42);
147 try expect(info.array.child == u8);
148 try expect(info.array.sentinel() == null);
149 }
150
151 {
152 const info = @typeInfo([10:0]u8);
153 try expect(info.array.len == 10);
154 try expect(info.array.child == u8);
155 try expect(info.array.sentinel().? == @as(u8, 0));
156 try expect(@sizeOf([10:0]u8) == info.array.len + 1);
157 }
158}
159
160test "type info: error set, error union info, anyerror" {
161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
162 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
164
165 try testErrorSet();
166 try comptime testErrorSet();
167}
168
169fn testErrorSet() !void {
170 const TestErrorSet = error{
171 First,
172 Second,
173 Third,
174 };
175
176 const error_set_info = @typeInfo(TestErrorSet);
177 try expect(error_set_info == .error_set);
178 try expect(error_set_info.error_set.error_names.?.len == 3);
179 try expect(mem.eql(u8, error_set_info.error_set.error_names.?[0], "First"));
180
181 const error_union_info = @typeInfo(TestErrorSet!usize);
182 try expect(error_union_info == .error_union);
183 try expect(error_union_info.error_union.error_set == TestErrorSet);
184 try expect(error_union_info.error_union.payload == usize);
185
186 const global_info = @typeInfo(anyerror);
187 try expect(global_info == .error_set);
188 try expect(global_info.error_set.error_names == null);
189}
190
191test "type info: error set single value" {
192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
193 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
194 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
195
196 const TestSet = error.One;
197
198 const error_set_info = @typeInfo(@TypeOf(TestSet));
199 try expect(error_set_info == .error_set);
200 try expect(error_set_info.error_set.error_names.?.len == 1);
201 try expect(mem.eql(u8, error_set_info.error_set.error_names.?[0], "One"));
202}
203
204test "type info: error set merged" {
205 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
207 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
208
209 const TestSet = error{ One, Two } || error{Three};
210
211 const error_set_info = @typeInfo(TestSet);
212 try expect(error_set_info == .error_set);
213 try expect(error_set_info.error_set.error_names.?.len == 3);
214 try expect(mem.eql(u8, error_set_info.error_set.error_names.?[0], "One"));
215 try expect(mem.eql(u8, error_set_info.error_set.error_names.?[1], "Two"));
216 try expect(mem.eql(u8, error_set_info.error_set.error_names.?[2], "Three"));
217}
218
219test "type info: enum info" {
220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
222 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
223
224 try testEnum();
225 try comptime testEnum();
226}
227
228fn testEnum() !void {
229 const Os = enum {
230 Windows,
231 Macos,
232 Linux,
233 FreeBSD,
234 };
235
236 const os_info = @typeInfo(Os);
237 try expect(os_info == .@"enum");
238 try expect(os_info.@"enum".field_names.len == 4);
239 try expect(os_info.@"enum".field_values.len == os_info.@"enum".field_names.len);
240 try expect(mem.eql(u8, os_info.@"enum".field_names[1], "Macos"));
241 try expect(os_info.@"enum".field_values[3] == 3);
242 try expect(os_info.@"enum".tag_type == u2);
243 try expect(os_info.@"enum".decl_names.len == 0);
244}
245
246test "type info: union info" {
247 try testUnion();
248 try comptime testUnion();
249}
250
251fn testUnion() !void {
252 const typeinfo_info = @typeInfo(Type);
253 try expect(typeinfo_info == .@"union");
254 try expect(typeinfo_info.@"union".layout == .auto);
255 try expect(typeinfo_info.@"union".tag_type.? == TypeId);
256 try expect(typeinfo_info.@"union".field_names.len == 25);
257 try expect(typeinfo_info.@"union".field_names.len == typeinfo_info.@"union".field_types.len);
258 try expect(typeinfo_info.@"union".field_names.len == typeinfo_info.@"union".field_attrs.len);
259 try expect(typeinfo_info.@"union".field_types[4] == @TypeOf(@typeInfo(u8).int));
260 try expect(typeinfo_info.@"union".decl_names.len == 17);
261
262 const TestNoTagUnion = union {
263 Foo: void,
264 Bar: u32,
265 };
266
267 const notag_union_info = @typeInfo(TestNoTagUnion);
268 try expect(notag_union_info == .@"union");
269 try expect(notag_union_info.@"union".tag_type == null);
270 try expect(notag_union_info.@"union".layout == .auto);
271 try expect(notag_union_info.@"union".field_names.len == 2);
272 try expect(notag_union_info.@"union".field_names.len == notag_union_info.@"union".field_types.len);
273 try expect(notag_union_info.@"union".field_names.len == notag_union_info.@"union".field_attrs.len);
274 try expect(notag_union_info.@"union".field_attrs[0].@"align" == null);
275 try expect(notag_union_info.@"union".field_types[1] == u32);
276 try expect(notag_union_info.@"union".field_attrs[1].@"align" == null);
277
278 const TestExternUnion = extern union {
279 foo: *anyopaque,
280 };
281
282 const extern_union_info = @typeInfo(TestExternUnion);
283 try expect(extern_union_info.@"union".layout == .@"extern");
284 try expect(extern_union_info.@"union".tag_type == null);
285 try expect(extern_union_info.@"union".field_types[0] == *anyopaque);
286}
287
288test "type info: struct info" {
289 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
290 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
291
292 try testStruct();
293 try comptime testStruct();
294}
295
296fn testStruct() !void {
297 const unpacked_struct_info = @typeInfo(TestStruct);
298 try expect(unpacked_struct_info.@"struct".is_tuple == false);
299 try expect(unpacked_struct_info.@"struct".backing_integer == null);
300 try expect(unpacked_struct_info.@"struct".field_attrs[0].@"align" == null);
301 const field_0_type = unpacked_struct_info.@"struct".field_types[0];
302 try expect(unpacked_struct_info.@"struct".field_attrs[0].defaultValue(field_0_type).? == 4);
303 const field_1_type = unpacked_struct_info.@"struct".field_types[1];
304 try expect(mem.eql(u8, "foobar", unpacked_struct_info.@"struct".field_attrs[1].defaultValue(field_1_type).?));
305}
306
307const TestStruct = struct {
308 fieldA: u32 = 4,
309 fieldB: *const [6:0]u8 = "foobar",
310};
311
312test "type info: packed struct info" {
313 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
314
315 try testPackedStruct();
316 try comptime testPackedStruct();
317}
318
319fn testPackedStruct() !void {
320 const struct_info = @typeInfo(TestPackedStruct);
321 try expect(struct_info == .@"struct");
322 try expect(struct_info.@"struct".is_tuple == false);
323 try expect(struct_info.@"struct".layout == .@"packed");
324 try expect(struct_info.@"struct".backing_integer == u128);
325 try expect(struct_info.@"struct".field_names.len == 4);
326 try expect(struct_info.@"struct".field_names.len == struct_info.@"struct".field_types.len);
327 try expect(struct_info.@"struct".field_names.len == struct_info.@"struct".field_attrs.len);
328 try expect(struct_info.@"struct".field_attrs[0].@"align" == null);
329 try expect(struct_info.@"struct".field_types[2] == f32);
330 const field_2_type = struct_info.@"struct".field_types[2];
331 try expect(struct_info.@"struct".field_attrs[2].defaultValue(field_2_type) == null);
332 const field_3_type = struct_info.@"struct".field_types[3];
333 try expect(struct_info.@"struct".field_attrs[3].defaultValue(field_3_type).? == 4);
334 try expect(struct_info.@"struct".field_attrs[3].@"align" == null);
335 try expect(struct_info.@"struct".decl_names.len == 1);
336}
337
338const TestPackedStruct = packed struct {
339 fieldA: u64,
340 fieldB: void,
341 fieldC: f32,
342 fieldD: u32 = 4,
343
344 pub fn foo(self: *const Self) void {
345 _ = self;
346 }
347 const Self = @This();
348};
349
350test "type info: opaque info" {
351 try testOpaque();
352 try comptime testOpaque();
353}
354
355fn testOpaque() !void {
356 const Foo = opaque {
357 pub const A = 1;
358 pub fn b() void {}
359 };
360
361 const foo_info = @typeInfo(Foo);
362 try expect(foo_info.@"opaque".decl_names.len == 2);
363}
364
365test "type info: function type info" {
366 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
367 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
368
369 try testFunction();
370 try comptime testFunction();
371}
372
373fn testFunction() !void {
374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
375
376 const S = struct {
377 export fn typeInfoFoo() callconv(.c) usize {
378 unreachable;
379 }
380 export fn typeInfoFooAligned() callconv(.c) usize {
381 unreachable;
382 }
383 };
384 _ = S;
385 const foo_fn_type = @TypeOf(typeInfoFoo);
386 const foo_fn_info = @typeInfo(foo_fn_type);
387 try expect(foo_fn_info.@"fn".attrs.@"callconv".eql(.c));
388 try expect(!foo_fn_info.@"fn".is_generic);
389 try expect(foo_fn_info.@"fn".param_types.len == 2);
390 try expect(foo_fn_info.@"fn".attrs.varargs);
391 try expect(foo_fn_info.@"fn".return_type.? == usize);
392 const foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFoo));
393 try expect(foo_ptr_fn_info.pointer.size == .one);
394 try expect(foo_ptr_fn_info.pointer.attrs.@"const");
395 try expect(!foo_ptr_fn_info.pointer.attrs.@"volatile");
396 try expect(foo_ptr_fn_info.pointer.attrs.@"addrspace" == .generic);
397 try expect(foo_ptr_fn_info.pointer.child == foo_fn_type);
398 try expect(!foo_ptr_fn_info.pointer.attrs.@"allowzero");
399 try expect(foo_ptr_fn_info.pointer.sentinel() == null);
400
401 // Avoid looking at `typeInfoFooAligned` on targets which don't support function alignment.
402 switch (builtin.target.cpu.arch) {
403 .spirv32,
404 .spirv64,
405 .wasm32,
406 .wasm64,
407 => return,
408 else => {},
409 }
410
411 const aligned_foo_fn_type = @TypeOf(typeInfoFooAligned);
412 const aligned_foo_fn_info = @typeInfo(aligned_foo_fn_type);
413 try expect(aligned_foo_fn_info.@"fn".attrs.@"callconv".eql(.c));
414 try expect(!aligned_foo_fn_info.@"fn".is_generic);
415 try expect(aligned_foo_fn_info.@"fn".param_types.len == 2);
416 try expect(aligned_foo_fn_info.@"fn".param_types.len == aligned_foo_fn_info.@"fn".param_attrs.len);
417 try expect(aligned_foo_fn_info.@"fn".attrs.varargs);
418 try expect(aligned_foo_fn_info.@"fn".return_type.? == usize);
419 const aligned_foo_ptr_fn_info = @typeInfo(@TypeOf(&typeInfoFooAligned));
420 try expect(aligned_foo_ptr_fn_info.pointer.size == .one);
421 try expect(aligned_foo_ptr_fn_info.pointer.attrs.@"const");
422 try expect(!aligned_foo_ptr_fn_info.pointer.attrs.@"volatile");
423 try expect(aligned_foo_ptr_fn_info.pointer.attrs.@"align" == 4);
424 try expect(aligned_foo_ptr_fn_info.pointer.attrs.@"addrspace" == .generic);
425 try expect(aligned_foo_ptr_fn_info.pointer.child == aligned_foo_fn_type);
426 try expect(!aligned_foo_ptr_fn_info.pointer.attrs.@"allowzero");
427 try expect(aligned_foo_ptr_fn_info.pointer.sentinel() == null);
428}
429
430extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.c) usize;
431extern fn typeInfoFooAligned(a: usize, b: bool, ...) align(4) callconv(.c) usize;
432
433test "type info: generic function types" {
434 const G1 = @typeInfo(@TypeOf(generic1));
435 try expect(G1.@"fn".param_types.len == 1);
436 try expect(G1.@"fn".param_types.len == G1.@"fn".param_attrs.len);
437 try expect(G1.@"fn".param_types[0] == null);
438 try expect(G1.@"fn".return_type == void);
439
440 const G2 = @typeInfo(@TypeOf(generic2));
441 try expect(G2.@"fn".param_types.len == 3);
442 try expect(G2.@"fn".param_types.len == G2.@"fn".param_attrs.len);
443 try expect(G2.@"fn".param_types[0] == type);
444 try expect(G2.@"fn".param_types[1] == null);
445 try expect(G2.@"fn".param_types[2] == u8);
446 try expect(G2.@"fn".return_type == void);
447
448 const G3 = @typeInfo(@TypeOf(generic3));
449 try expect(G3.@"fn".param_types.len == 1);
450 try expect(G3.@"fn".param_types.len == G3.@"fn".param_attrs.len);
451 try expect(G3.@"fn".param_types[0] == null);
452 try expect(G3.@"fn".return_type == null);
453
454 const G4 = @typeInfo(@TypeOf(generic4));
455 try expect(G4.@"fn".param_types.len == 1);
456 try expect(G4.@"fn".param_types.len == G4.@"fn".param_attrs.len);
457 try expect(G4.@"fn".param_types[0] == null);
458 try expect(G4.@"fn".return_type == null);
459}
460
461fn generic1(param: anytype) void {
462 _ = param;
463}
464fn generic2(comptime T: type, param: T, param2: u8) void {
465 _ = param;
466 _ = param2;
467}
468fn generic3(param: anytype) @TypeOf(param) {}
469fn generic4(comptime param: anytype) @TypeOf(param) {}
470
471test "typeInfo with comptime parameter in struct fn def" {
472 const S = struct {
473 pub fn func(comptime x: f32) void {
474 _ = x;
475 }
476 };
477 comptime var info = @typeInfo(S);
478 _ = &info;
479}
480
481test "type info: vectors" {
482 try testVector();
483 try comptime testVector();
484}
485
486fn testVector() !void {
487 const vec_info = @typeInfo(@Vector(4, i32));
488 try expect(vec_info == .vector);
489 try expect(vec_info.vector.len == 4);
490 try expect(vec_info.vector.child == i32);
491}
492
493test "type info: anyframe and anyframe->T" {
494 if (true) {
495 // https://github.com/ziglang/zig/issues/6025
496 return error.SkipZigTest;
497 }
498
499 try testAnyFrame();
500 try comptime testAnyFrame();
501}
502
503fn testAnyFrame() !void {
504 {
505 const anyframe_info = @typeInfo(anyframe->i32);
506 try expect(anyframe_info == .@"anyframe");
507 try expect(anyframe_info.@"anyframe".child.? == i32);
508 }
509
510 {
511 const anyframe_info = @typeInfo(anyframe);
512 try expect(anyframe_info == .@"anyframe");
513 try expect(anyframe_info.@"anyframe".child == null);
514 }
515}
516
517test "type info: pass to function" {
518 _ = passTypeInfo(@typeInfo(void));
519 _ = comptime passTypeInfo(@typeInfo(void));
520}
521
522fn passTypeInfo(comptime info: Type) type {
523 _ = info;
524 return void;
525}
526
527test "type info: TypeId -> Type impl cast" {
528 _ = passTypeInfo(TypeId.void);
529 _ = comptime passTypeInfo(TypeId.void);
530}
531
532test "sentinel of opaque pointer type" {
533 const c_void_info = @typeInfo(*anyopaque);
534 try expect(c_void_info.pointer.sentinel_ptr == null);
535}
536
537test "@typeInfo does not force declarations into existence" {
538 const S = struct {
539 x: i32,
540
541 fn doNotReferenceMe() void {
542 @compileError("test failed");
543 }
544 };
545 comptime assert(@typeInfo(S).@"struct".field_names.len == 1);
546}
547
548fn add(a: i32, b: i32) i32 {
549 return a + b;
550}
551
552test "Declarations are returned in declaration order" {
553 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
554 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
555
556 const S = struct {
557 pub const a = 1;
558 pub const b = 2;
559 pub const c = 3;
560 pub const d = 4;
561 pub const e = 5;
562 };
563 const d = @typeInfo(S).@"struct".decl_names;
564 try expect(std.mem.eql(u8, d[0], "a"));
565 try expect(std.mem.eql(u8, d[1], "b"));
566 try expect(std.mem.eql(u8, d[2], "c"));
567 try expect(std.mem.eql(u8, d[3], "d"));
568 try expect(std.mem.eql(u8, d[4], "e"));
569}
570
571test "Struct.is_tuple for anon list literal" {
572 try expect(@typeInfo(@TypeOf(.{0})).@"struct".is_tuple);
573}
574
575test "Struct.is_tuple for anon struct literal" {
576 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
577
578 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
579
580 const info = @typeInfo(@TypeOf(.{ .a = 0 }));
581 try expect(!info.@"struct".is_tuple);
582 try expect(std.mem.eql(u8, info.@"struct".field_names[0], "a"));
583}
584
585test "StructField.is_comptime" {
586 const info = @typeInfo(struct { x: u8 = 3, comptime y: u32 = 5 }).@"struct";
587 try expect(!info.field_attrs[0].@"comptime");
588 try expect(info.field_attrs[1].@"comptime");
589}
590
591test "value from struct @typeInfo default_value_ptr can be loaded at comptime" {
592 comptime {
593 const a = @typeInfo(@TypeOf(.{ .foo = @as(u8, 1) })).@"struct".field_attrs[0].default_value_ptr;
594 try expect(@as(*const u8, @ptrCast(a)).* == 1);
595 }
596}
597
598test "type info of tuple of string literal default value" {
599 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
600
601 const struct_info = @typeInfo(@TypeOf(.{"hi"})).@"struct";
602 const struct_field_attrs = struct_info.field_attrs[0];
603 const struct_field_type = struct_info.field_types[0];
604 const value = struct_field_attrs.defaultValue(struct_field_type).?;
605 comptime std.debug.assert(value[0] == 'h');
606}
607
608test "@typeInfo function with generic return type and inferred error set" {
609 const S = struct {
610 fn testFn(comptime T: type) !T {}
611 };
612
613 const ret_ty = @typeInfo(@TypeOf(S.testFn)).@"fn".return_type;
614 comptime assert(ret_ty == null);
615}
616
617test "type info: spirv info" {
618 if (builtin.zig_backend != .stage2_spirv) return error.SkipZigTest;
619
620 try testSpirv();
621 try comptime testSpirv();
622}
623
624fn testSpirv() !void {
625 const image_info = @typeInfo(Image);
626 try expect(image_info.spirv.image.usage.sampled == f32);
627 try expect(image_info.spirv.image.format == .unknown);
628 try expect(image_info.spirv.image.dim == .@"2d");
629 try expect(image_info.spirv.image.depth == .not_depth);
630 try expect(image_info.spirv.image.arrayed == false);
631 try expect(image_info.spirv.image.multisampled == false);
632 try expect(image_info.spirv.image.access == .unknown);
633
634 const sampled_image_info = @typeInfo(SampledImage);
635 try expect(sampled_image_info.spirv.sampled_image == Image);
636
637 const sampler_info = @typeInfo(Sampler);
638 try expect(sampler_info.spirv.sampler == {});
639
640 const runtime_array_info = @typeInfo(RuntimeArray);
641 try expect(runtime_array_info.spirv.runtime_array == f32);
642}
643
644pub const Image = @SpirvType(.{ .image = .{
645 .usage = .{ .sampled = f32 },
646 .format = .unknown,
647 .dim = .@"2d",
648 .depth = .not_depth,
649 .arrayed = false,
650 .multisampled = false,
651 .access = .unknown,
652} });
653pub const SampledImage = @SpirvType(.{ .sampled_image = Image });
654pub const Sampler = @SpirvType(.sampler);
655pub const RuntimeArray = @SpirvType(.{ .runtime_array = f32 });