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