| ... | ... | @@ -0,0 +1,181 @@ |
| 1 | const assert = @import("std").debug.assert; |
| 2 | const mem = @import("std").mem; |
| 3 | const TypeInfo = @import("builtin").TypeInfo; |
| 4 | const TypeId = @import("builtin").TypeId; |
| 5 | |
| 6 | test "type info: tag type, void info" { |
| 7 | comptime { |
| 8 | assert(@TagType(TypeInfo) == TypeId); |
| 9 | const void_info = @typeInfo(void); |
| 10 | assert(TypeId(void_info) == TypeId.Void); |
| 11 | assert(void_info.Void == {}); |
| 12 | } |
| 13 | } |
| 14 | |
| 15 | test "type info: integer, floating point type info" { |
| 16 | comptime { |
| 17 | const u8_info = @typeInfo(u8); |
| 18 | assert(TypeId(u8_info) == TypeId.Int); |
| 19 | assert(!u8_info.Int.is_signed); |
| 20 | assert(u8_info.Int.bits == 8); |
| 21 | |
| 22 | const f64_info = @typeInfo(f64); |
| 23 | assert(TypeId(f64_info) == TypeId.Float); |
| 24 | assert(f64_info.Float.bits == 64); |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | test "type info: pointer, array and nullable type info" { |
| 29 | comptime { |
| 30 | const u32_ptr_info = @typeInfo(&u32); |
| 31 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); |
| 32 | assert(u32_ptr_info.Pointer.is_const == false); |
| 33 | assert(u32_ptr_info.Pointer.is_volatile == false); |
| 34 | assert(u32_ptr_info.Pointer.alignment == 4); |
| 35 | assert(u32_ptr_info.Pointer.child == u32); |
| 36 | |
| 37 | const arr_info = @typeInfo([42]bool); |
| 38 | assert(TypeId(arr_info) == TypeId.Array); |
| 39 | assert(arr_info.Array.len == 42); |
| 40 | assert(arr_info.Array.child == bool); |
| 41 | |
| 42 | const null_info = @typeInfo(?void); |
| 43 | assert(TypeId(null_info) == TypeId.Nullable); |
| 44 | assert(null_info.Nullable.child == void); |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | test "type info: promise info" { |
| 49 | comptime { |
| 50 | const null_promise_info = @typeInfo(promise); |
| 51 | assert(TypeId(null_promise_info) == TypeId.Promise); |
| 52 | assert(null_promise_info.Promise.child == @typeOf(undefined)); |
| 53 | |
| 54 | const promise_info = @typeInfo(promise->usize); |
| 55 | assert(TypeId(promise_info) == TypeId.Promise); |
| 56 | assert(promise_info.Promise.child == usize); |
| 57 | } |
| 58 | |
| 59 | } |
| 60 | |
| 61 | test "type info: error set, error union info" { |
| 62 | comptime { |
| 63 | const TestErrorSet = error { |
| 64 | First, |
| 65 | Second, |
| 66 | Third, |
| 67 | }; |
| 68 | |
| 69 | const error_set_info = @typeInfo(TestErrorSet); |
| 70 | assert(TypeId(error_set_info) == TypeId.ErrorSet); |
| 71 | assert(error_set_info.ErrorSet.errors.len == 3); |
| 72 | assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); |
| 73 | assert(error_set_info.ErrorSet.errors[2].value == 3); |
| 74 | |
| 75 | const error_union_info = @typeInfo(TestErrorSet!usize); |
| 76 | assert(TypeId(error_union_info) == TypeId.ErrorUnion); |
| 77 | assert(error_union_info.ErrorUnion.error_set == TestErrorSet); |
| 78 | assert(error_union_info.ErrorUnion.payload == usize); |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | test "type info: enum info" { |
| 83 | comptime { |
| 84 | const Os = @import("builtin").Os; |
| 85 | |
| 86 | const os_info = @typeInfo(Os); |
| 87 | assert(TypeId(os_info) == TypeId.Enum); |
| 88 | assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); |
| 89 | assert(os_info.Enum.fields.len == 32); |
| 90 | assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas")); |
| 91 | assert(os_info.Enum.fields[10].value == 10); |
| 92 | assert(os_info.Enum.tag_type == u5); |
| 93 | assert(os_info.Enum.defs.len == 0); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | test "type info: union info" { |
| 98 | comptime { |
| 99 | const typeinfo_info = @typeInfo(TypeInfo); |
| 100 | assert(TypeId(typeinfo_info) == TypeId.Union); |
| 101 | assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); |
| 102 | assert(typeinfo_info.Union.tag_type == TypeId); |
| 103 | assert(typeinfo_info.Union.fields.len == 25); |
| 104 | assert(typeinfo_info.Union.fields[4].enum_field != null); |
| 105 | assert((??typeinfo_info.Union.fields[4].enum_field).value == 4); |
| 106 | assert(typeinfo_info.Union.fields[4].field_type == @typeOf(u8_info.Int)); |
| 107 | assert(typeinfo_info.Union.defs.len == 20); |
| 108 | |
| 109 | const TestNoTagUnion = union { |
| 110 | Foo: void, |
| 111 | Bar: u32, |
| 112 | }; |
| 113 | |
| 114 | const notag_union_info = @typeInfo(TestNoTagUnion); |
| 115 | assert(TypeId(notag_union_info) == TypeId.Union); |
| 116 | assert(notag_union_info.Union.tag_type == @typeOf(undefined)); |
| 117 | assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); |
| 118 | assert(notag_union_info.Union.fields.len == 2); |
| 119 | assert(notag_union_info.Union.fields[0].enum_field == null); |
| 120 | assert(notag_union_info.Union.fields[1].field_type == u32); |
| 121 | |
| 122 | const TestExternUnion = extern union { |
| 123 | foo: &c_void, |
| 124 | }; |
| 125 | |
| 126 | const extern_union_info = @typeInfo(TestExternUnion); |
| 127 | assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); |
| 128 | assert(extern_union_info.Union.tag_type == @typeOf(undefined)); |
| 129 | assert(extern_union_info.Union.fields[0].enum_field == null); |
| 130 | assert(extern_union_info.Union.fields[0].field_type == &c_void); |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | test "type info: struct info" { |
| 135 | comptime { |
| 136 | const struct_info = @typeInfo(TestStruct); |
| 137 | assert(TypeId(struct_info) == TypeId.Struct); |
| 138 | assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); |
| 139 | assert(struct_info.Struct.fields.len == 3); |
| 140 | assert(struct_info.Struct.fields[1].offset == null); |
| 141 | assert(struct_info.Struct.fields[2].field_type == &TestStruct); |
| 142 | assert(struct_info.Struct.defs.len == 2); |
| 143 | assert(struct_info.Struct.defs[0].is_pub); |
| 144 | assert(!struct_info.Struct.defs[0].data.Fn.is_extern); |
| 145 | assert(struct_info.Struct.defs[0].data.Fn.lib_name == null); |
| 146 | assert(struct_info.Struct.defs[0].data.Fn.return_type == void); |
| 147 | assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void); |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | const TestStruct = packed struct { |
| 152 | const Self = this; |
| 153 | |
| 154 | fieldA: usize, |
| 155 | fieldB: void, |
| 156 | fieldC: &Self, |
| 157 | |
| 158 | pub fn foo(self: &const Self) void {} |
| 159 | }; |
| 160 | |
| 161 | test "type info: function type info" { |
| 162 | comptime { |
| 163 | const fn_info = @typeInfo(@typeOf(foo)); |
| 164 | assert(TypeId(fn_info) == TypeId.Fn); |
| 165 | assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); |
| 166 | assert(fn_info.Fn.is_generic); |
| 167 | assert(fn_info.Fn.args.len == 2); |
| 168 | assert(fn_info.Fn.is_var_args); |
| 169 | assert(fn_info.Fn.return_type == @typeOf(undefined)); |
| 170 | assert(fn_info.Fn.async_allocator_type == @typeOf(undefined)); |
| 171 | |
| 172 | const test_instance: TestStruct = undefined; |
| 173 | const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); |
| 174 | assert(TypeId(bound_fn_info) == TypeId.BoundFn); |
| 175 | assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct); |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | fn foo(comptime a: usize, b: bool, args: ...) usize { |
| 180 | return 0; |
| 181 | } |