| author | |
| committer | |
| log | c70633eacdf4e17cfafe0ab44f4ea83323b6d7a3 |
| tree | 8154639afe68f601754de51366af3a6c817eb558 |
| parent | b9e3df92db1b5cb137d880a7612b6ee2e7e1f60e |
| parent | a62e9bc8e50296e2d5b201614a78b0e658887aa9 |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
implement @typeInfo for Frame and implement @Type for Frame, EnumLiteral, and ErrorSet7 files changed, 171 insertions(+), 23 deletions(-)
lib/std/builtin.zig+17-10| ... | ... | @@ -166,7 +166,7 @@ pub const TypeInfo = union(enum) { |
| 166 | 166 | Fn: Fn, |
| 167 | 167 | BoundFn: Fn, |
| 168 | 168 | Opaque: void, |
| 169 | Frame: void, | |
| 169 | Frame: Frame, | |
| 170 | 170 | AnyFrame: AnyFrame, |
| 171 | 171 | Vector: Vector, |
| 172 | 172 | EnumLiteral: void, |
| ... | ... | @@ -244,8 +244,8 @@ pub const TypeInfo = union(enum) { |
| 244 | 244 | /// therefore must be kept in sync with the compiler implementation. |
| 245 | 245 | pub const Struct = struct { |
| 246 | 246 | layout: ContainerLayout, |
| 247 | fields: []StructField, | |
| 248 | decls: []Declaration, | |
| 247 | fields: []const StructField, | |
| 248 | decls: []const Declaration, | |
| 249 | 249 | }; |
| 250 | 250 | |
| 251 | 251 | /// This data structure is used by the Zig language code generation and |
| ... | ... | @@ -265,12 +265,13 @@ pub const TypeInfo = union(enum) { |
| 265 | 265 | /// therefore must be kept in sync with the compiler implementation. |
| 266 | 266 | pub const Error = struct { |
| 267 | 267 | name: []const u8, |
| 268 | /// This field is ignored when using @Type(). | |
| 268 | 269 | value: comptime_int, |
| 269 | 270 | }; |
| 270 | 271 | |
| 271 | 272 | /// This data structure is used by the Zig language code generation and |
| 272 | 273 | /// therefore must be kept in sync with the compiler implementation. |
| 273 | pub const ErrorSet = ?[]Error; | |
| 274 | pub const ErrorSet = ?[]const Error; | |
| 274 | 275 | |
| 275 | 276 | /// This data structure is used by the Zig language code generation and |
| 276 | 277 | /// therefore must be kept in sync with the compiler implementation. |
| ... | ... | @@ -284,8 +285,8 @@ pub const TypeInfo = union(enum) { |
| 284 | 285 | pub const Enum = struct { |
| 285 | 286 | layout: ContainerLayout, |
| 286 | 287 | tag_type: type, |
| 287 | fields: []EnumField, | |
| 288 | decls: []Declaration, | |
| 288 | fields: []const EnumField, | |
| 289 | decls: []const Declaration, | |
| 289 | 290 | is_exhaustive: bool, |
| 290 | 291 | }; |
| 291 | 292 | |
| ... | ... | @@ -302,8 +303,8 @@ pub const TypeInfo = union(enum) { |
| 302 | 303 | pub const Union = struct { |
| 303 | 304 | layout: ContainerLayout, |
| 304 | 305 | tag_type: ?type, |
| 305 | fields: []UnionField, | |
| 306 | decls: []Declaration, | |
| 306 | fields: []const UnionField, | |
| 307 | decls: []const Declaration, | |
| 307 | 308 | }; |
| 308 | 309 | |
| 309 | 310 | /// This data structure is used by the Zig language code generation and |
| ... | ... | @@ -321,7 +322,13 @@ pub const TypeInfo = union(enum) { |
| 321 | 322 | is_generic: bool, |
| 322 | 323 | is_var_args: bool, |
| 323 | 324 | return_type: ?type, |
| 324 | args: []FnArg, | |
| 325 | args: []const FnArg, | |
| 326 | }; | |
| 327 | ||
| 328 | /// This data structure is used by the Zig language code generation and | |
| 329 | /// therefore must be kept in sync with the compiler implementation. | |
| 330 | pub const Frame = struct { | |
| 331 | function: var, | |
| 325 | 332 | }; |
| 326 | 333 | |
| 327 | 334 | /// This data structure is used by the Zig language code generation and |
| ... | ... | @@ -361,7 +368,7 @@ pub const TypeInfo = union(enum) { |
| 361 | 368 | is_export: bool, |
| 362 | 369 | lib_name: ?[]const u8, |
| 363 | 370 | return_type: type, |
| 364 | arg_names: [][]const u8, | |
| 371 | arg_names: []const []const u8, | |
| 365 | 372 | |
| 366 | 373 | /// This data structure is used by the Zig language code generation and |
| 367 | 374 | /// therefore must be kept in sync with the compiler implementation. |
lib/std/meta.zig+6-6| ... | ... | @@ -250,7 +250,7 @@ test "std.meta.containerLayout" { |
| 250 | 250 | testing.expect(containerLayout(U3) == .Extern); |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | pub fn declarations(comptime T: type) []TypeInfo.Declaration { | |
| 253 | pub fn declarations(comptime T: type) []const TypeInfo.Declaration { | |
| 254 | 254 | return switch (@typeInfo(T)) { |
| 255 | 255 | .Struct => |info| info.decls, |
| 256 | 256 | .Enum => |info| info.decls, |
| ... | ... | @@ -274,7 +274,7 @@ test "std.meta.declarations" { |
| 274 | 274 | fn a() void {} |
| 275 | 275 | }; |
| 276 | 276 | |
| 277 | const decls = comptime [_][]TypeInfo.Declaration{ | |
| 277 | const decls = comptime [_][]const TypeInfo.Declaration{ | |
| 278 | 278 | declarations(E1), |
| 279 | 279 | declarations(S1), |
| 280 | 280 | declarations(U1), |
| ... | ... | @@ -323,10 +323,10 @@ test "std.meta.declarationInfo" { |
| 323 | 323 | } |
| 324 | 324 | |
| 325 | 325 | pub fn fields(comptime T: type) switch (@typeInfo(T)) { |
| 326 | .Struct => []TypeInfo.StructField, | |
| 327 | .Union => []TypeInfo.UnionField, | |
| 328 | .ErrorSet => []TypeInfo.Error, | |
| 329 | .Enum => []TypeInfo.EnumField, | |
| 326 | .Struct => []const TypeInfo.StructField, | |
| 327 | .Union => []const TypeInfo.UnionField, | |
| 328 | .ErrorSet => []const TypeInfo.Error, | |
| 329 | .Enum => []const TypeInfo.EnumField, | |
| 330 | 330 | else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), |
| 331 | 331 | } { |
| 332 | 332 | return switch (@typeInfo(T)) { |
src/analyze.cpp+13| ... | ... | @@ -6012,6 +6012,19 @@ ZigValue *create_const_null(CodeGen *g, ZigType *type) { |
| 6012 | 6012 | return const_val; |
| 6013 | 6013 | } |
| 6014 | 6014 | |
| 6015 | void init_const_fn(ZigValue *const_val, ZigFn *fn) { | |
| 6016 | const_val->special = ConstValSpecialStatic; | |
| 6017 | const_val->type = fn->type_entry; | |
| 6018 | const_val->data.x_ptr.special = ConstPtrSpecialFunction; | |
| 6019 | const_val->data.x_ptr.data.fn.fn_entry = fn; | |
| 6020 | } | |
| 6021 | ||
| 6022 | ZigValue *create_const_fn(CodeGen *g, ZigFn *fn) { | |
| 6023 | ZigValue *const_val = g->pass1_arena->create<ZigValue>(); | |
| 6024 | init_const_fn(const_val, fn); | |
| 6025 | return const_val; | |
| 6026 | } | |
| 6027 | ||
| 6015 | 6028 | void init_const_float(ZigValue *const_val, ZigType *type, double value) { |
| 6016 | 6029 | const_val->special = ConstValSpecialStatic; |
| 6017 | 6030 | const_val->type = type; |
src/analyze.hpp+3| ... | ... | @@ -180,6 +180,9 @@ ZigValue *create_const_slice(CodeGen *g, ZigValue *array_val, size_t start, size |
| 180 | 180 | void init_const_null(ZigValue *const_val, ZigType *type); |
| 181 | 181 | ZigValue *create_const_null(CodeGen *g, ZigType *type); |
| 182 | 182 | |
| 183 | void init_const_fn(ZigValue *const_val, ZigFn *fn); | |
| 184 | ZigValue *create_const_fn(CodeGen *g, ZigFn *fn); | |
| 185 | ||
| 183 | 186 | ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count); |
| 184 | 187 | ZigValue **realloc_const_vals_ptrs(CodeGen *g, ZigValue **ptr, size_t old_count, size_t new_count); |
| 185 | 188 |
src/ir.cpp+95-6| ... | ... | @@ -25610,9 +25610,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy |
| 25610 | 25610 | break; |
| 25611 | 25611 | } |
| 25612 | 25612 | case ZigTypeIdFnFrame: |
| 25613 | ir_add_error(ira, source_instr, | |
| 25614 | buf_sprintf("compiler bug: TODO @typeInfo for async function frames. https://github.com/ziglang/zig/issues/3066")); | |
| 25615 | return ErrorSemanticAnalyzeFail; | |
| 25613 | { | |
| 25614 | result = ira->codegen->pass1_arena->create<ZigValue>(); | |
| 25615 | result->special = ConstValSpecialStatic; | |
| 25616 | result->type = ir_type_info_get_type(ira, "Frame", nullptr); | |
| 25617 | ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 1); | |
| 25618 | result->data.x_struct.fields = fields; | |
| 25619 | ZigFn *fn = type_entry->data.frame.fn; | |
| 25620 | // function: var | |
| 25621 | ensure_field_index(result->type, "function", 0); | |
| 25622 | fields[0] = create_const_fn(ira->codegen, fn); | |
| 25623 | break; | |
| 25624 | } | |
| 25616 | 25625 | } |
| 25617 | 25626 | |
| 25618 | 25627 | assert(result != nullptr); |
| ... | ... | @@ -25881,10 +25890,90 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI |
| 25881 | 25890 | ZigType *child_type = get_const_field_meta_type_optional(ira, source_instr->source_node, payload, "child", 0); |
| 25882 | 25891 | return get_any_frame_type(ira->codegen, child_type); |
| 25883 | 25892 | } |
| 25884 | case ZigTypeIdErrorSet: | |
| 25885 | case ZigTypeIdEnum: | |
| 25886 | case ZigTypeIdFnFrame: | |
| 25887 | 25893 | case ZigTypeIdEnumLiteral: |
| 25894 | return ira->codegen->builtin_types.entry_enum_literal; | |
| 25895 | case ZigTypeIdFnFrame: { | |
| 25896 | assert(payload->special == ConstValSpecialStatic); | |
| 25897 | assert(payload->type == ir_type_info_get_type(ira, "Frame", nullptr)); | |
| 25898 | ZigValue *function = get_const_field(ira, source_instr->source_node, payload, "function", 0); | |
| 25899 | assert(function->type->id == ZigTypeIdFn); | |
| 25900 | ZigFn *fn = function->data.x_ptr.data.fn.fn_entry; | |
| 25901 | return get_fn_frame_type(ira->codegen, fn); | |
| 25902 | } | |
| 25903 | case ZigTypeIdErrorSet: { | |
| 25904 | assert(payload->special == ConstValSpecialStatic); | |
| 25905 | assert(payload->type->id == ZigTypeIdOptional); | |
| 25906 | ZigValue *slice = payload->data.x_optional; | |
| 25907 | if (slice == nullptr) | |
| 25908 | return ira->codegen->builtin_types.entry_global_error_set; | |
| 25909 | assert(slice->special == ConstValSpecialStatic); | |
| 25910 | assert(is_slice(slice->type)); | |
| 25911 | ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); | |
| 25912 | Buf bare_name = BUF_INIT; | |
| 25913 | buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->old_irb.exec, "error", source_instr->scope, source_instr->source_node, &bare_name)); | |
| 25914 | err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits; | |
| 25915 | err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align; | |
| 25916 | err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size; | |
| 25917 | ZigValue *ptr = slice->data.x_struct.fields[slice_ptr_index]; | |
| 25918 | assert(ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);; | |
| 25919 | assert(ptr->data.x_ptr.data.base_array.elem_index == 0); | |
| 25920 | ZigValue *arr = ptr->data.x_ptr.data.base_array.array_val; | |
| 25921 | assert(arr->special == ConstValSpecialStatic); | |
| 25922 | assert(arr->data.x_array.special == ConstArraySpecialNone); | |
| 25923 | ZigValue *len = slice->data.x_struct.fields[slice_len_index]; | |
| 25924 | size_t count = bigint_as_usize(&len->data.x_bigint); | |
| 25925 | err_set_type->data.error_set.err_count = count; | |
| 25926 | err_set_type->data.error_set.errors = heap::c_allocator.allocate<ErrorTableEntry *>(count); | |
| 25927 | bool *already_set = heap::c_allocator.allocate<bool>(ira->codegen->errors_by_index.length + count); | |
| 25928 | for (size_t i = 0; i < count; i++) { | |
| 25929 | ZigValue *error = &arr->data.x_array.data.s_none.elements[i]; | |
| 25930 | assert(error->type == ir_type_info_get_type(ira, "Error", nullptr)); | |
| 25931 | ErrorTableEntry *err_entry = heap::c_allocator.create<ErrorTableEntry>(); | |
| 25932 | err_entry->decl_node = source_instr->source_node; | |
| 25933 | ZigValue *name_slice = get_const_field(ira, source_instr->source_node, error, "name", 0); | |
| 25934 | ZigValue *name_ptr = name_slice->data.x_struct.fields[slice_ptr_index]; | |
| 25935 | ZigValue *name_len = name_slice->data.x_struct.fields[slice_len_index]; | |
| 25936 | assert(name_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray); | |
| 25937 | assert(name_ptr->data.x_ptr.data.base_array.elem_index == 0); | |
| 25938 | ZigValue *name_arr = name_ptr->data.x_ptr.data.base_array.array_val; | |
| 25939 | assert(name_arr->special == ConstValSpecialStatic); | |
| 25940 | switch (name_arr->data.x_array.special) { | |
| 25941 | case ConstArraySpecialUndef: | |
| 25942 | return ira->codegen->invalid_inst_gen->value->type; | |
| 25943 | case ConstArraySpecialNone: { | |
| 25944 | buf_resize(&err_entry->name, 0); | |
| 25945 | size_t name_count = bigint_as_usize(&name_len->data.x_bigint); | |
| 25946 | for (size_t j = 0; j < name_count; j++) { | |
| 25947 | ZigValue *ch_val = &name_arr->data.x_array.data.s_none.elements[j]; | |
| 25948 | unsigned ch = bigint_as_u32(&ch_val->data.x_bigint); | |
| 25949 | buf_append_char(&err_entry->name, ch); | |
| 25950 | } | |
| 25951 | break; | |
| 25952 | } | |
| 25953 | case ConstArraySpecialBuf: | |
| 25954 | buf_init_from_buf(&err_entry->name, name_arr->data.x_array.data.s_buf); | |
| 25955 | break; | |
| 25956 | } | |
| 25957 | auto existing_entry = ira->codegen->error_table.put_unique(&err_entry->name, err_entry); | |
| 25958 | if (existing_entry) { | |
| 25959 | err_entry->value = existing_entry->value->value; | |
| 25960 | } else { | |
| 25961 | size_t error_value_count = ira->codegen->errors_by_index.length; | |
| 25962 | assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count)); | |
| 25963 | err_entry->value = error_value_count; | |
| 25964 | ira->codegen->errors_by_index.append(err_entry); | |
| 25965 | } | |
| 25966 | if (already_set[err_entry->value]) { | |
| 25967 | ir_add_error(ira, source_instr, buf_sprintf("duplicate error: %s", buf_ptr(&err_entry->name))); | |
| 25968 | return ira->codegen->invalid_inst_gen->value->type; | |
| 25969 | } else { | |
| 25970 | already_set[err_entry->value] = true; | |
| 25971 | } | |
| 25972 | err_set_type->data.error_set.errors[i] = err_entry; | |
| 25973 | } | |
| 25974 | return err_set_type; | |
| 25975 | } | |
| 25976 | case ZigTypeIdEnum: | |
| 25888 | 25977 | ir_add_error(ira, source_instr, buf_sprintf( |
| 25889 | 25978 | "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId))); |
| 25890 | 25979 | return ira->codegen->invalid_inst_gen->value->type; |
test/stage1/behavior/type.zig+23| ... | ... | @@ -213,3 +213,26 @@ test "Type.AnyFrame" { |
| 213 | 213 | anyframe->anyframe->u8, |
| 214 | 214 | }); |
| 215 | 215 | } |
| 216 | ||
| 217 | test "Type.EnumLiteral" { | |
| 218 | testTypes(&[_]type{ | |
| 219 | @TypeOf(.Dummy), | |
| 220 | }); | |
| 221 | } | |
| 222 | ||
| 223 | fn add(a: i32, b: i32) i32 { | |
| 224 | return a + b; | |
| 225 | } | |
| 226 | ||
| 227 | test "Type.Frame" { | |
| 228 | testTypes(&[_]type{ | |
| 229 | @Frame(add), | |
| 230 | }); | |
| 231 | } | |
| 232 | ||
| 233 | test "Type.ErrorSet" { | |
| 234 | // error sets don't compare equal so just check if they compile | |
| 235 | _ = @Type(@typeInfo(error{})); | |
| 236 | _ = @Type(@typeInfo(error{A})); | |
| 237 | _ = @Type(@typeInfo(error{ A, B, C })); | |
| 238 | } |
test/stage1/behavior/type_info.zig+14-1| ... | ... | @@ -202,7 +202,7 @@ fn testUnion() void { |
| 202 | 202 | expect(typeinfo_info.Union.fields[4].enum_field != null); |
| 203 | 203 | expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4); |
| 204 | 204 | expect(typeinfo_info.Union.fields[4].field_type == @TypeOf(@typeInfo(u8).Int)); |
| 205 | expect(typeinfo_info.Union.decls.len == 20); | |
| 205 | expect(typeinfo_info.Union.decls.len == 21); | |
| 206 | 206 | |
| 207 | 207 | const TestNoTagUnion = union { |
| 208 | 208 | Foo: void, |
| ... | ... | @@ -389,3 +389,16 @@ test "defaut value for a var-typed field" { |
| 389 | 389 | const S = struct { x: var }; |
| 390 | 390 | expect(@typeInfo(S).Struct.fields[0].default_value == null); |
| 391 | 391 | } |
| 392 | ||
| 393 | fn add(a: i32, b: i32) i32 { | |
| 394 | return a + b; | |
| 395 | } | |
| 396 | ||
| 397 | test "type info for async frames" { | |
| 398 | switch (@typeInfo(@Frame(add))) { | |
| 399 | .Frame => |frame| { | |
| 400 | expect(frame.function == add); | |
| 401 | }, | |
| 402 | else => unreachable, | |
| 403 | } | |
| 404 | } |