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