| author | |
| committer | |
| log | d3693dca73dfc726aed32908691437abe614e5cf |
| tree | 167e2d8c24c6a653f05723716b796949a0eb5585 |
| parent | 76c8efd56c84c189a52d3dc559fff109d5d34ce4 |
* add assertion for trying to do @typeInfo on global error set
* remove TypeInfo.Slice
* add TypeInfo.Pointer.Size with possible values
- One
- Many
- Slice
See #7705 files changed, 102 insertions(+), 55 deletions(-)
src/analyze.cpp+1-1| ... | @@ -5981,7 +5981,7 @@ size_t type_id_index(TypeTableEntry *entry) { | ... | @@ -5981,7 +5981,7 @@ size_t type_id_index(TypeTableEntry *entry) { |
| 5981 | return 7; | 5981 | return 7; |
| 5982 | case TypeTableEntryIdStruct: | 5982 | case TypeTableEntryIdStruct: |
| 5983 | if (entry->data.structure.is_slice) | 5983 | if (entry->data.structure.is_slice) |
| 5984 | return 25; | 5984 | return 6; |
| 5985 | return 8; | 5985 | return 8; |
| 5986 | case TypeTableEntryIdComptimeFloat: | 5986 | case TypeTableEntryIdComptimeFloat: |
| 5987 | return 9; | 5987 | return 9; |
src/codegen.cpp+7-4| ... | @@ -6481,7 +6481,6 @@ static void define_builtin_compile_vars(CodeGen *g) { | ... | @@ -6481,7 +6481,6 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 6481 | const TypeTableEntryId id = type_id_at_index(i); | 6481 | const TypeTableEntryId id = type_id_at_index(i); |
| 6482 | buf_appendf(contents, " %s,\n", type_id_name(id)); | 6482 | buf_appendf(contents, " %s,\n", type_id_name(id)); |
| 6483 | } | 6483 | } |
| 6484 | buf_appendf(contents, " Slice,\n"); | ||
| 6485 | buf_appendf(contents, "};\n\n"); | 6484 | buf_appendf(contents, "};\n\n"); |
| 6486 | } | 6485 | } |
| 6487 | { | 6486 | { |
| ... | @@ -6494,7 +6493,6 @@ static void define_builtin_compile_vars(CodeGen *g) { | ... | @@ -6494,7 +6493,6 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 6494 | " Int: Int,\n" | 6493 | " Int: Int,\n" |
| 6495 | " Float: Float,\n" | 6494 | " Float: Float,\n" |
| 6496 | " Pointer: Pointer,\n" | 6495 | " Pointer: Pointer,\n" |
| 6497 | " Slice: Slice,\n" | ||
| 6498 | " Array: Array,\n" | 6496 | " Array: Array,\n" |
| 6499 | " Struct: Struct,\n" | 6497 | " Struct: Struct,\n" |
| 6500 | " ComptimeFloat: void,\n" | 6498 | " ComptimeFloat: void,\n" |
| ... | @@ -6524,13 +6522,18 @@ static void define_builtin_compile_vars(CodeGen *g) { | ... | @@ -6524,13 +6522,18 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 6524 | " };\n" | 6522 | " };\n" |
| 6525 | "\n" | 6523 | "\n" |
| 6526 | " pub const Pointer = struct {\n" | 6524 | " pub const Pointer = struct {\n" |
| 6525 | " size: Size,\n" | ||
| 6527 | " is_const: bool,\n" | 6526 | " is_const: bool,\n" |
| 6528 | " is_volatile: bool,\n" | 6527 | " is_volatile: bool,\n" |
| 6529 | " alignment: u32,\n" | 6528 | " alignment: u32,\n" |
| 6530 | " child: type,\n" | 6529 | " child: type,\n" |
| 6531 | " };\n" | ||
| 6532 | "\n" | 6530 | "\n" |
| 6533 | " pub const Slice = Pointer;\n" | 6531 | " pub const Size = enum {\n" |
| 6532 | " One,\n" | ||
| 6533 | " Many,\n" | ||
| 6534 | " Slice,\n" | ||
| 6535 | " };\n" | ||
| 6536 | " };\n" | ||
| 6534 | "\n" | 6537 | "\n" |
| 6535 | " pub const Array = struct {\n" | 6538 | " pub const Array = struct {\n" |
| 6536 | " len: usize,\n" | 6539 | " len: usize,\n" |
src/ir.cpp+50-30| ... | @@ -16222,8 +16222,7 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop | ... | @@ -16222,8 +16222,7 @@ static bool ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Scop |
| 16222 | return true; | 16222 | return true; |
| 16223 | } | 16223 | } |
| 16224 | 16224 | ||
| 16225 | static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) | 16225 | static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) { |
| 16226 | { | ||
| 16227 | assert(type_entry != nullptr); | 16226 | assert(type_entry != nullptr); |
| 16228 | assert(!type_is_invalid(type_entry)); | 16227 | assert(!type_is_invalid(type_entry)); |
| 16229 | 16228 | ||
| ... | @@ -16248,38 +16247,67 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t | ... | @@ -16248,38 +16247,67 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16248 | enum_field_val->data.x_struct.fields = inner_fields; | 16247 | enum_field_val->data.x_struct.fields = inner_fields; |
| 16249 | }; | 16248 | }; |
| 16250 | 16249 | ||
| 16251 | const auto create_ptr_like_type_info = [ira](const char *name, TypeTableEntry *ptr_type_entry) { | 16250 | const auto create_ptr_like_type_info = [ira](TypeTableEntry *ptr_type_entry) { |
| 16251 | TypeTableEntry *attrs_type; | ||
| 16252 | uint32_t size_enum_index; | ||
| 16253 | if (is_slice(ptr_type_entry)) { | ||
| 16254 | attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry; | ||
| 16255 | size_enum_index = 2; | ||
| 16256 | } else if (ptr_type_entry->id == TypeTableEntryIdPointer) { | ||
| 16257 | attrs_type = ptr_type_entry; | ||
| 16258 | size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1; | ||
| 16259 | } else { | ||
| 16260 | zig_unreachable(); | ||
| 16261 | } | ||
| 16262 | |||
| 16263 | TypeTableEntry *type_info_pointer_type = ir_type_info_get_type(ira, "Pointer"); | ||
| 16264 | ensure_complete_type(ira->codegen, type_info_pointer_type); | ||
| 16265 | assert(!type_is_invalid(type_info_pointer_type)); | ||
| 16266 | |||
| 16252 | ConstExprValue *result = create_const_vals(1); | 16267 | ConstExprValue *result = create_const_vals(1); |
| 16253 | result->special = ConstValSpecialStatic; | 16268 | result->special = ConstValSpecialStatic; |
| 16254 | result->type = ir_type_info_get_type(ira, name); | 16269 | result->type = type_info_pointer_type; |
| 16255 | 16270 | ||
| 16256 | ConstExprValue *fields = create_const_vals(4); | 16271 | ConstExprValue *fields = create_const_vals(5); |
| 16257 | result->data.x_struct.fields = fields; | 16272 | result->data.x_struct.fields = fields; |
| 16258 | 16273 | ||
| 16259 | // is_const: bool | 16274 | // size: Size |
| 16260 | ensure_field_index(result->type, "is_const", 0); | 16275 | ensure_field_index(result->type, "size", 0); |
| 16276 | TypeTableEntry *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type); | ||
| 16277 | ensure_complete_type(ira->codegen, type_info_pointer_size_type); | ||
| 16278 | assert(!type_is_invalid(type_info_pointer_size_type)); | ||
| 16261 | fields[0].special = ConstValSpecialStatic; | 16279 | fields[0].special = ConstValSpecialStatic; |
| 16262 | fields[0].type = ira->codegen->builtin_types.entry_bool; | 16280 | fields[0].type = type_info_pointer_size_type; |
| 16263 | fields[0].data.x_bool = ptr_type_entry->data.pointer.is_const; | 16281 | bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index); |
| 16264 | // is_volatile: bool | 16282 | |
| 16265 | ensure_field_index(result->type, "is_volatile", 1); | 16283 | // is_const: bool |
| 16284 | ensure_field_index(result->type, "is_const", 1); | ||
| 16266 | fields[1].special = ConstValSpecialStatic; | 16285 | fields[1].special = ConstValSpecialStatic; |
| 16267 | fields[1].type = ira->codegen->builtin_types.entry_bool; | 16286 | fields[1].type = ira->codegen->builtin_types.entry_bool; |
| 16268 | fields[1].data.x_bool = ptr_type_entry->data.pointer.is_volatile; | 16287 | fields[1].data.x_bool = attrs_type->data.pointer.is_const; |
| 16269 | // alignment: u32 | 16288 | // is_volatile: bool |
| 16270 | ensure_field_index(result->type, "alignment", 2); | 16289 | ensure_field_index(result->type, "is_volatile", 2); |
| 16271 | fields[2].special = ConstValSpecialStatic; | 16290 | fields[2].special = ConstValSpecialStatic; |
| 16272 | fields[2].type = ira->codegen->builtin_types.entry_u32; | 16291 | fields[2].type = ira->codegen->builtin_types.entry_bool; |
| 16273 | bigint_init_unsigned(&fields[2].data.x_bigint, ptr_type_entry->data.pointer.alignment); | 16292 | fields[2].data.x_bool = attrs_type->data.pointer.is_volatile; |
| 16274 | // child: type | 16293 | // alignment: u32 |
| 16275 | ensure_field_index(result->type, "child", 3); | 16294 | ensure_field_index(result->type, "alignment", 3); |
| 16276 | fields[3].special = ConstValSpecialStatic; | 16295 | fields[3].special = ConstValSpecialStatic; |
| 16277 | fields[3].type = ira->codegen->builtin_types.entry_type; | 16296 | fields[3].type = ira->codegen->builtin_types.entry_u32; |
| 16278 | fields[3].data.x_type = ptr_type_entry->data.pointer.child_type; | 16297 | bigint_init_unsigned(&fields[3].data.x_bigint, attrs_type->data.pointer.alignment); |
| 16298 | // child: type | ||
| 16299 | ensure_field_index(result->type, "child", 4); | ||
| 16300 | fields[4].special = ConstValSpecialStatic; | ||
| 16301 | fields[4].type = ira->codegen->builtin_types.entry_type; | ||
| 16302 | fields[4].data.x_type = attrs_type->data.pointer.child_type; | ||
| 16279 | 16303 | ||
| 16280 | return result; | 16304 | return result; |
| 16281 | }; | 16305 | }; |
| 16282 | 16306 | ||
| 16307 | if (type_entry == ira->codegen->builtin_types.entry_global_error_set) { | ||
| 16308 | zig_panic("TODO implement @typeInfo for global error set"); | ||
| 16309 | } | ||
| 16310 | |||
| 16283 | ConstExprValue *result = nullptr; | 16311 | ConstExprValue *result = nullptr; |
| 16284 | switch (type_entry->id) | 16312 | switch (type_entry->id) |
| 16285 | { | 16313 | { |
| ... | @@ -16348,7 +16376,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t | ... | @@ -16348,7 +16376,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16348 | } | 16376 | } |
| 16349 | case TypeTableEntryIdPointer: | 16377 | case TypeTableEntryIdPointer: |
| 16350 | { | 16378 | { |
| 16351 | result = create_ptr_like_type_info("Pointer", type_entry); | 16379 | result = create_ptr_like_type_info(type_entry); |
| 16352 | break; | 16380 | break; |
| 16353 | } | 16381 | } |
| 16354 | case TypeTableEntryIdArray: | 16382 | case TypeTableEntryIdArray: |
| ... | @@ -16621,15 +16649,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t | ... | @@ -16621,15 +16649,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16621 | case TypeTableEntryIdStruct: | 16649 | case TypeTableEntryIdStruct: |
| 16622 | { | 16650 | { |
| 16623 | if (type_entry->data.structure.is_slice) { | 16651 | if (type_entry->data.structure.is_slice) { |
| 16624 | Buf ptr_field_name = BUF_INIT; | 16652 | result = create_ptr_like_type_info(type_entry); |
| 16625 | buf_init_from_str(&ptr_field_name, "ptr"); | ||
| 16626 | TypeTableEntry *ptr_type = type_entry->data.structure.fields_by_name.get(&ptr_field_name)->type_entry; | ||
| 16627 | ensure_complete_type(ira->codegen, ptr_type); | ||
| 16628 | if (type_is_invalid(ptr_type)) | ||
| 16629 | return nullptr; | ||
| 16630 | buf_deinit(&ptr_field_name); | ||
| 16631 | |||
| 16632 | result = create_ptr_like_type_info("Slice", ptr_type); | ||
| 16633 | break; | 16653 | break; |
| 16634 | } | 16654 | } |
| 16635 | 16655 |
std/fmt/index.zig+19-12| ... | @@ -97,7 +97,11 @@ pub fn formatType( | ... | @@ -97,7 +97,11 @@ pub fn formatType( |
| 97 | output: fn (@typeOf(context), []const u8) Errors!void, | 97 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 98 | ) Errors!void { | 98 | ) Errors!void { |
| 99 | const T = @typeOf(value); | 99 | const T = @typeOf(value); |
| 100 | switch (@typeId(T)) { | 100 | if (T == error) { |
| 101 | try output(context, "error."); | ||
| 102 | return output(context, @errorName(value)); | ||
| 103 | } | ||
| 104 | switch (@typeInfo(T)) { | ||
| 101 | builtin.TypeId.Int, builtin.TypeId.Float => { | 105 | builtin.TypeId.Int, builtin.TypeId.Float => { |
| 102 | return formatValue(value, fmt, context, Errors, output); | 106 | return formatValue(value, fmt, context, Errors, output); |
| 103 | }, | 107 | }, |
| ... | @@ -125,12 +129,13 @@ pub fn formatType( | ... | @@ -125,12 +129,13 @@ pub fn formatType( |
| 125 | try output(context, "error."); | 129 | try output(context, "error."); |
| 126 | return output(context, @errorName(value)); | 130 | return output(context, @errorName(value)); |
| 127 | }, | 131 | }, |
| 128 | builtin.TypeId.Pointer => { | 132 | builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) { |
| 129 | switch (@typeId(T.Child)) { | 133 | builtin.TypeInfo.Pointer.Size.One => switch (@typeInfo(ptr_info.child)) { |
| 130 | builtin.TypeId.Array => { | 134 | builtin.TypeId.Array => |info| { |
| 131 | if (T.Child.Child == u8) { | 135 | if (info.child == u8) { |
| 132 | return formatText(value, fmt, context, Errors, output); | 136 | return formatText(value, fmt, context, Errors, output); |
| 133 | } | 137 | } |
| 138 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); | ||
| 134 | }, | 139 | }, |
| 135 | builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { | 140 | builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { |
| 136 | const has_cust_fmt = comptime cf: { | 141 | const has_cust_fmt = comptime cf: { |
| ... | @@ -154,14 +159,16 @@ pub fn formatType( | ... | @@ -154,14 +159,16 @@ pub fn formatType( |
| 154 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); | 159 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); |
| 155 | }, | 160 | }, |
| 156 | else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)), | 161 | else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)), |
| 157 | } | 162 | }, |
| 158 | }, | 163 | builtin.TypeInfo.Pointer.Size.Many => { |
| 159 | else => if (@canImplicitCast([]const u8, value)) { | 164 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); |
| 160 | const casted_value = ([]const u8)(value); | 165 | }, |
| 161 | return output(context, casted_value); | 166 | builtin.TypeInfo.Pointer.Size.Slice => { |
| 162 | } else { | 167 | const casted_value = ([]const u8)(value); |
| 163 | @compileError("Unable to format type '" ++ @typeName(T) ++ "'"); | 168 | return output(context, casted_value); |
| 169 | }, | ||
| 164 | }, | 170 | }, |
| 171 | else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), | ||
| 165 | } | 172 | } |
| 166 | } | 173 | } |
| 167 | 174 |
test/cases/type_info.zig+25-8| ... | @@ -39,12 +39,28 @@ test "type info: pointer type info" { | ... | @@ -39,12 +39,28 @@ test "type info: pointer type info" { |
| 39 | fn testPointer() void { | 39 | fn testPointer() void { |
| 40 | const u32_ptr_info = @typeInfo(*u32); | 40 | const u32_ptr_info = @typeInfo(*u32); |
| 41 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); | 41 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); |
| 42 | assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); | ||
| 42 | assert(u32_ptr_info.Pointer.is_const == false); | 43 | assert(u32_ptr_info.Pointer.is_const == false); |
| 43 | assert(u32_ptr_info.Pointer.is_volatile == false); | 44 | assert(u32_ptr_info.Pointer.is_volatile == false); |
| 44 | assert(u32_ptr_info.Pointer.alignment == 4); | 45 | assert(u32_ptr_info.Pointer.alignment == @alignOf(u32)); |
| 45 | assert(u32_ptr_info.Pointer.child == u32); | 46 | assert(u32_ptr_info.Pointer.child == u32); |
| 46 | } | 47 | } |
| 47 | 48 | ||
| 49 | test "type info: unknown length pointer type info" { | ||
| 50 | testUnknownLenPtr(); | ||
| 51 | comptime testUnknownLenPtr(); | ||
| 52 | } | ||
| 53 | |||
| 54 | fn testUnknownLenPtr() void { | ||
| 55 | const u32_ptr_info = @typeInfo([*]const volatile f64); | ||
| 56 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); | ||
| 57 | assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); | ||
| 58 | assert(u32_ptr_info.Pointer.is_const == true); | ||
| 59 | assert(u32_ptr_info.Pointer.is_volatile == true); | ||
| 60 | assert(u32_ptr_info.Pointer.alignment == @alignOf(f64)); | ||
| 61 | assert(u32_ptr_info.Pointer.child == f64); | ||
| 62 | } | ||
| 63 | |||
| 48 | test "type info: slice type info" { | 64 | test "type info: slice type info" { |
| 49 | testSlice(); | 65 | testSlice(); |
| 50 | comptime testSlice(); | 66 | comptime testSlice(); |
| ... | @@ -52,11 +68,12 @@ test "type info: slice type info" { | ... | @@ -52,11 +68,12 @@ test "type info: slice type info" { |
| 52 | 68 | ||
| 53 | fn testSlice() void { | 69 | fn testSlice() void { |
| 54 | const u32_slice_info = @typeInfo([]u32); | 70 | const u32_slice_info = @typeInfo([]u32); |
| 55 | assert(TypeId(u32_slice_info) == TypeId.Slice); | 71 | assert(TypeId(u32_slice_info) == TypeId.Pointer); |
| 56 | assert(u32_slice_info.Slice.is_const == false); | 72 | assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); |
| 57 | assert(u32_slice_info.Slice.is_volatile == false); | 73 | assert(u32_slice_info.Pointer.is_const == false); |
| 58 | assert(u32_slice_info.Slice.alignment == 4); | 74 | assert(u32_slice_info.Pointer.is_volatile == false); |
| 59 | assert(u32_slice_info.Slice.child == u32); | 75 | assert(u32_slice_info.Pointer.alignment == 4); |
| 76 | assert(u32_slice_info.Pointer.child == u32); | ||
| 60 | } | 77 | } |
| 61 | 78 | ||
| 62 | test "type info: array type info" { | 79 | test "type info: array type info" { |
| ... | @@ -149,11 +166,11 @@ fn testUnion() void { | ... | @@ -149,11 +166,11 @@ fn testUnion() void { |
| 149 | assert(TypeId(typeinfo_info) == TypeId.Union); | 166 | assert(TypeId(typeinfo_info) == TypeId.Union); |
| 150 | assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); | 167 | assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); |
| 151 | assert(typeinfo_info.Union.tag_type == TypeId); | 168 | assert(typeinfo_info.Union.tag_type == TypeId); |
| 152 | assert(typeinfo_info.Union.fields.len == 26); | 169 | assert(typeinfo_info.Union.fields.len == 25); |
| 153 | assert(typeinfo_info.Union.fields[4].enum_field != null); | 170 | assert(typeinfo_info.Union.fields[4].enum_field != null); |
| 154 | assert((??typeinfo_info.Union.fields[4].enum_field).value == 4); | 171 | assert((??typeinfo_info.Union.fields[4].enum_field).value == 4); |
| 155 | assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); | 172 | assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); |
| 156 | assert(typeinfo_info.Union.defs.len == 21); | 173 | assert(typeinfo_info.Union.defs.len == 20); |
| 157 | 174 | ||
| 158 | const TestNoTagUnion = union { | 175 | const TestNoTagUnion = union { |
| 159 | Foo: void, | 176 | Foo: void, |