| 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 | 5981 | return 7; |
| 5982 | 5982 | case TypeTableEntryIdStruct: |
| 5983 | 5983 | if (entry->data.structure.is_slice) |
| 5984 | return 25; | |
| 5984 | return 6; | |
| 5985 | 5985 | return 8; |
| 5986 | 5986 | case TypeTableEntryIdComptimeFloat: |
| 5987 | 5987 | return 9; |
src/codegen.cpp+7-4| ... | ... | @@ -6481,7 +6481,6 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 6481 | 6481 | const TypeTableEntryId id = type_id_at_index(i); |
| 6482 | 6482 | buf_appendf(contents, " %s,\n", type_id_name(id)); |
| 6483 | 6483 | } |
| 6484 | buf_appendf(contents, " Slice,\n"); | |
| 6485 | 6484 | buf_appendf(contents, "};\n\n"); |
| 6486 | 6485 | } |
| 6487 | 6486 | { |
| ... | ... | @@ -6494,7 +6493,6 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 6494 | 6493 | " Int: Int,\n" |
| 6495 | 6494 | " Float: Float,\n" |
| 6496 | 6495 | " Pointer: Pointer,\n" |
| 6497 | " Slice: Slice,\n" | |
| 6498 | 6496 | " Array: Array,\n" |
| 6499 | 6497 | " Struct: Struct,\n" |
| 6500 | 6498 | " ComptimeFloat: void,\n" |
| ... | ... | @@ -6524,13 +6522,18 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 6524 | 6522 | " };\n" |
| 6525 | 6523 | "\n" |
| 6526 | 6524 | " pub const Pointer = struct {\n" |
| 6525 | " size: Size,\n" | |
| 6527 | 6526 | " is_const: bool,\n" |
| 6528 | 6527 | " is_volatile: bool,\n" |
| 6529 | 6528 | " alignment: u32,\n" |
| 6530 | 6529 | " child: type,\n" |
| 6531 | " };\n" | |
| 6532 | 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 | 6537 | "\n" |
| 6535 | 6538 | " pub const Array = struct {\n" |
| 6536 | 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 | 16222 | return true; |
| 16223 | 16223 | } |
| 16224 | 16224 | |
| 16225 | static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) | |
| 16226 | { | |
| 16225 | static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *type_entry) { | |
| 16227 | 16226 | assert(type_entry != nullptr); |
| 16228 | 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 | 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 | 16267 | ConstExprValue *result = create_const_vals(1); |
| 16253 | 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 | 16272 | result->data.x_struct.fields = fields; |
| 16258 | 16273 | |
| 16259 | // is_const: bool | |
| 16260 | ensure_field_index(result->type, "is_const", 0); | |
| 16274 | // size: Size | |
| 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 | 16279 | fields[0].special = ConstValSpecialStatic; |
| 16262 | fields[0].type = ira->codegen->builtin_types.entry_bool; | |
| 16263 | fields[0].data.x_bool = ptr_type_entry->data.pointer.is_const; | |
| 16264 | // is_volatile: bool | |
| 16265 | ensure_field_index(result->type, "is_volatile", 1); | |
| 16280 | fields[0].type = type_info_pointer_size_type; | |
| 16281 | bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index); | |
| 16282 | ||
| 16283 | // is_const: bool | |
| 16284 | ensure_field_index(result->type, "is_const", 1); | |
| 16266 | 16285 | fields[1].special = ConstValSpecialStatic; |
| 16267 | 16286 | fields[1].type = ira->codegen->builtin_types.entry_bool; |
| 16268 | fields[1].data.x_bool = ptr_type_entry->data.pointer.is_volatile; | |
| 16269 | // alignment: u32 | |
| 16270 | ensure_field_index(result->type, "alignment", 2); | |
| 16287 | fields[1].data.x_bool = attrs_type->data.pointer.is_const; | |
| 16288 | // is_volatile: bool | |
| 16289 | ensure_field_index(result->type, "is_volatile", 2); | |
| 16271 | 16290 | fields[2].special = ConstValSpecialStatic; |
| 16272 | fields[2].type = ira->codegen->builtin_types.entry_u32; | |
| 16273 | bigint_init_unsigned(&fields[2].data.x_bigint, ptr_type_entry->data.pointer.alignment); | |
| 16274 | // child: type | |
| 16275 | ensure_field_index(result->type, "child", 3); | |
| 16291 | fields[2].type = ira->codegen->builtin_types.entry_bool; | |
| 16292 | fields[2].data.x_bool = attrs_type->data.pointer.is_volatile; | |
| 16293 | // alignment: u32 | |
| 16294 | ensure_field_index(result->type, "alignment", 3); | |
| 16276 | 16295 | fields[3].special = ConstValSpecialStatic; |
| 16277 | fields[3].type = ira->codegen->builtin_types.entry_type; | |
| 16278 | fields[3].data.x_type = ptr_type_entry->data.pointer.child_type; | |
| 16296 | fields[3].type = ira->codegen->builtin_types.entry_u32; | |
| 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 | 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 | 16311 | ConstExprValue *result = nullptr; |
| 16284 | 16312 | switch (type_entry->id) |
| 16285 | 16313 | { |
| ... | ... | @@ -16348,7 +16376,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16348 | 16376 | } |
| 16349 | 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 | 16380 | break; |
| 16353 | 16381 | } |
| 16354 | 16382 | case TypeTableEntryIdArray: |
| ... | ... | @@ -16621,15 +16649,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t |
| 16621 | 16649 | case TypeTableEntryIdStruct: |
| 16622 | 16650 | { |
| 16623 | 16651 | if (type_entry->data.structure.is_slice) { |
| 16624 | Buf ptr_field_name = BUF_INIT; | |
| 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); | |
| 16652 | result = create_ptr_like_type_info(type_entry); | |
| 16633 | 16653 | break; |
| 16634 | 16654 | } |
| 16635 | 16655 |
std/fmt/index.zig+19-12| ... | ... | @@ -97,7 +97,11 @@ pub fn formatType( |
| 97 | 97 | output: fn (@typeOf(context), []const u8) Errors!void, |
| 98 | 98 | ) Errors!void { |
| 99 | 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 | 105 | builtin.TypeId.Int, builtin.TypeId.Float => { |
| 102 | 106 | return formatValue(value, fmt, context, Errors, output); |
| 103 | 107 | }, |
| ... | ... | @@ -125,12 +129,13 @@ pub fn formatType( |
| 125 | 129 | try output(context, "error."); |
| 126 | 130 | return output(context, @errorName(value)); |
| 127 | 131 | }, |
| 128 | builtin.TypeId.Pointer => { | |
| 129 | switch (@typeId(T.Child)) { | |
| 130 | builtin.TypeId.Array => { | |
| 131 | if (T.Child.Child == u8) { | |
| 132 | builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) { | |
| 133 | builtin.TypeInfo.Pointer.Size.One => switch (@typeInfo(ptr_info.child)) { | |
| 134 | builtin.TypeId.Array => |info| { | |
| 135 | if (info.child == u8) { | |
| 132 | 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 | 140 | builtin.TypeId.Enum, builtin.TypeId.Union, builtin.TypeId.Struct => { |
| 136 | 141 | const has_cust_fmt = comptime cf: { |
| ... | ... | @@ -154,14 +159,16 @@ pub fn formatType( |
| 154 | 159 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); |
| 155 | 160 | }, |
| 156 | 161 | else => return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)), |
| 157 | } | |
| 158 | }, | |
| 159 | else => if (@canImplicitCast([]const u8, value)) { | |
| 160 | const casted_value = ([]const u8)(value); | |
| 161 | return output(context, casted_value); | |
| 162 | } else { | |
| 163 | @compileError("Unable to format type '" ++ @typeName(T) ++ "'"); | |
| 162 | }, | |
| 163 | builtin.TypeInfo.Pointer.Size.Many => { | |
| 164 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value)); | |
| 165 | }, | |
| 166 | builtin.TypeInfo.Pointer.Size.Slice => { | |
| 167 | const casted_value = ([]const u8)(value); | |
| 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 | 39 | fn testPointer() void { |
| 40 | 40 | const u32_ptr_info = @typeInfo(*u32); |
| 41 | 41 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); |
| 42 | assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); | |
| 42 | 43 | assert(u32_ptr_info.Pointer.is_const == false); |
| 43 | 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 | 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 | 64 | test "type info: slice type info" { |
| 49 | 65 | testSlice(); |
| 50 | 66 | comptime testSlice(); |
| ... | ... | @@ -52,11 +68,12 @@ test "type info: slice type info" { |
| 52 | 68 | |
| 53 | 69 | fn testSlice() void { |
| 54 | 70 | 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); | |
| 71 | assert(TypeId(u32_slice_info) == TypeId.Pointer); | |
| 72 | assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); | |
| 73 | assert(u32_slice_info.Pointer.is_const == false); | |
| 74 | assert(u32_slice_info.Pointer.is_volatile == false); | |
| 75 | assert(u32_slice_info.Pointer.alignment == 4); | |
| 76 | assert(u32_slice_info.Pointer.child == u32); | |
| 60 | 77 | } |
| 61 | 78 | |
| 62 | 79 | test "type info: array type info" { |
| ... | ... | @@ -149,11 +166,11 @@ fn testUnion() void { |
| 149 | 166 | assert(TypeId(typeinfo_info) == TypeId.Union); |
| 150 | 167 | assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); |
| 151 | 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 | 170 | assert(typeinfo_info.Union.fields[4].enum_field != null); |
| 154 | 171 | assert((??typeinfo_info.Union.fields[4].enum_field).value == 4); |
| 155 | 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 | 175 | const TestNoTagUnion = union { |
| 159 | 176 | Foo: void, |