authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-22 03:21:46-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-08-22 03:21:46-04:00
log55d7c399c136537551359eed6f73a70ac77f7091
treed77cf3c7e11e8679ad04ebf2cbf3f53545212ebc
parenta049c31f2184895c731636b6f71c5743200d64fc
parent351701bcadcd4fd00b1d69212d7ac203326ed02d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6119 from tadeokondrak/@Type(.Enum)

Implement @Type for Enum

4 files changed, 243 insertions(+), 115 deletions(-)

src/analyze.cpp+122-103
...@@ -2586,7 +2586,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2586,7 +2586,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2586 return ErrorNone;2586 return ErrorNone;
25872587
2588 AstNode *decl_node = enum_type->data.enumeration.decl_node;2588 AstNode *decl_node = enum_type->data.enumeration.decl_node;
2589 assert(decl_node->type == NodeTypeContainerDecl);
25902589
2591 if (enum_type->data.enumeration.resolve_loop_flag) {2590 if (enum_type->data.enumeration.resolve_loop_flag) {
2592 if (enum_type->data.enumeration.resolve_status != ResolveStatusInvalid) {2591 if (enum_type->data.enumeration.resolve_status != ResolveStatusInvalid) {
...@@ -2600,15 +2599,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2600,15 +2599,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
26002599
2601 enum_type->data.enumeration.resolve_loop_flag = true;2600 enum_type->data.enumeration.resolve_loop_flag = true;
26022601
2603 assert(!enum_type->data.enumeration.fields);2602 uint32_t field_count;
2604 uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length;2603 if (decl_node->type == NodeTypeContainerDecl) {
2605 if (field_count == 0) {2604 assert(!enum_type->data.enumeration.fields);
2606 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));2605 field_count = (uint32_t)decl_node->data.container_decl.fields.length;
2606 if (field_count == 0) {
2607 add_node_error(g, decl_node, buf_sprintf("enums must have 1 or more fields"));
26072608
2608 enum_type->data.enumeration.src_field_count = field_count;2609 enum_type->data.enumeration.src_field_count = field_count;
2609 enum_type->data.enumeration.fields = nullptr;2610 enum_type->data.enumeration.fields = nullptr;
2610 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;2611 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2611 return ErrorSemanticAnalyzeFail;2612 return ErrorSemanticAnalyzeFail;
2613 }
2614 } else {
2615 field_count = enum_type->data.enumeration.src_field_count;
2612 }2616 }
26132617
2614 Scope *scope = &enum_type->data.enumeration.decls_scope->base;2618 Scope *scope = &enum_type->data.enumeration.decls_scope->base;
...@@ -2624,8 +2628,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2624,8 +2628,16 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2624 enum_type->abi_size = tag_int_type->abi_size;2628 enum_type->abi_size = tag_int_type->abi_size;
2625 enum_type->abi_align = tag_int_type->abi_align;2629 enum_type->abi_align = tag_int_type->abi_align;
26262630
2627 if (decl_node->data.container_decl.init_arg_expr != nullptr) {2631 ZigType *wanted_tag_int_type = nullptr;
2628 ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);2632 if (decl_node->type == NodeTypeContainerDecl) {
2633 if (decl_node->data.container_decl.init_arg_expr != nullptr) {
2634 wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr);
2635 }
2636 } else {
2637 wanted_tag_int_type = enum_type->data.enumeration.tag_int_type;
2638 }
2639
2640 if (wanted_tag_int_type != nullptr) {
2629 if (type_is_invalid(wanted_tag_int_type)) {2641 if (type_is_invalid(wanted_tag_int_type)) {
2630 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;2642 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2631 } else if (wanted_tag_int_type->id != ZigTypeIdInt &&2643 } else if (wanted_tag_int_type->id != ZigTypeIdInt &&
...@@ -2654,7 +2666,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2654,7 +2666,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2654 }2666 }
2655 }2667 }
26562668
2657 enum_type->data.enumeration.non_exhaustive = false;
2658 enum_type->data.enumeration.tag_int_type = tag_int_type;2669 enum_type->data.enumeration.tag_int_type = tag_int_type;
2659 enum_type->size_in_bits = tag_int_type->size_in_bits;2670 enum_type->size_in_bits = tag_int_type->size_in_bits;
2660 enum_type->abi_size = tag_int_type->abi_size;2671 enum_type->abi_size = tag_int_type->abi_size;
...@@ -2663,121 +2674,131 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2663,121 +2674,131 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2663 BigInt bi_one;2674 BigInt bi_one;
2664 bigint_init_unsigned(&bi_one, 1);2675 bigint_init_unsigned(&bi_one, 1);
26652676
2666 AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1);2677 if (decl_node->type == NodeTypeContainerDecl) {
2667 if (buf_eql_str(last_field_node->data.struct_field.name, "_")) {2678 AstNode *last_field_node = decl_node->data.container_decl.fields.at(field_count - 1);
2679 if (buf_eql_str(last_field_node->data.struct_field.name, "_")) {
2680 if (last_field_node->data.struct_field.value != nullptr) {
2681 add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum"));
2682 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2683 }
2684 if (decl_node->data.container_decl.init_arg_expr == nullptr) {
2685 add_node_error(g, decl_node, buf_sprintf("non-exhaustive enum must specify size"));
2686 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2687 }
2688 enum_type->data.enumeration.non_exhaustive = true;
2689 } else {
2690 enum_type->data.enumeration.non_exhaustive = false;
2691 }
2692 }
2693
2694 if (enum_type->data.enumeration.non_exhaustive) {
2668 field_count -= 1;2695 field_count -= 1;
2669 if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) {2696 if (field_count > 1 && log2_u64(field_count) == enum_type->size_in_bits) {
2670 add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum specifies every value"));2697 add_node_error(g, decl_node, buf_sprintf("non-exhaustive enum specifies every value"));
2671 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;2698 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2672 }2699 }
2673 if (decl_node->data.container_decl.init_arg_expr == nullptr) {
2674 add_node_error(g, last_field_node, buf_sprintf("non-exhaustive enum must specify size"));
2675 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2676 }
2677 if (last_field_node->data.struct_field.value != nullptr) {
2678 add_node_error(g, last_field_node, buf_sprintf("value assigned to '_' field of non-exhaustive enum"));
2679 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2680 }
2681 enum_type->data.enumeration.non_exhaustive = true;
2682 }2700 }
26832701
2684 enum_type->data.enumeration.src_field_count = field_count;2702 if (decl_node->type == NodeTypeContainerDecl) {
2685 enum_type->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(field_count);2703 enum_type->data.enumeration.src_field_count = field_count;
2686 enum_type->data.enumeration.fields_by_name.init(field_count);2704 enum_type->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(field_count);
26872705 enum_type->data.enumeration.fields_by_name.init(field_count);
2688 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
2689 occupied_tag_values.init(field_count);
2690
2691 TypeEnumField *last_enum_field = nullptr;
2692
2693 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
2694 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
2695 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
2696 type_enum_field->name = field_node->data.struct_field.name;
2697 type_enum_field->decl_index = field_i;
2698 type_enum_field->decl_node = field_node;
26992706
2700 if (field_node->data.struct_field.type != nullptr) {2707 HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> occupied_tag_values = {};
2701 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type,2708 occupied_tag_values.init(field_count);
2702 buf_sprintf("structs and unions, not enums, support field types"));
2703 add_error_note(g, msg, decl_node,
2704 buf_sprintf("consider 'union(enum)' here"));
2705 } else if (field_node->data.struct_field.align_expr != nullptr) {
2706 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr,
2707 buf_sprintf("structs and unions, not enums, support field alignment"));
2708 add_error_note(g, msg, decl_node,
2709 buf_sprintf("consider 'union(enum)' here"));
2710 }
27112709
2712 if (buf_eql_str(type_enum_field->name, "_")) {2710 TypeEnumField *last_enum_field = nullptr;
2713 add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
2714 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2715 }
27162711
2717 auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);2712 for (uint32_t field_i = 0; field_i < field_count; field_i += 1) {
2718 if (field_entry != nullptr) {2713 AstNode *field_node = decl_node->data.container_decl.fields.at(field_i);
2719 ErrorMsg *msg = add_node_error(g, field_node,2714 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[field_i];
2720 buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));2715 type_enum_field->name = field_node->data.struct_field.name;
2721 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));2716 type_enum_field->decl_index = field_i;
2722 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;2717 type_enum_field->decl_node = field_node;
2723 continue;2718
2724 }2719 if (field_node->data.struct_field.type != nullptr) {
27252720 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.type,
2726 AstNode *tag_value = field_node->data.struct_field.value;2721 buf_sprintf("structs and unions, not enums, support field types"));
2722 add_error_note(g, msg, decl_node,
2723 buf_sprintf("consider 'union(enum)' here"));
2724 } else if (field_node->data.struct_field.align_expr != nullptr) {
2725 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.align_expr,
2726 buf_sprintf("structs and unions, not enums, support field alignment"));
2727 add_error_note(g, msg, decl_node,
2728 buf_sprintf("consider 'union(enum)' here"));
2729 }
2730
2731 if (buf_eql_str(type_enum_field->name, "_")) {
2732 add_node_error(g, field_node, buf_sprintf("'_' field of non-exhaustive enum must be last"));
2733 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2734 }
27272735
2728 if (tag_value != nullptr) {2736 auto field_entry = enum_type->data.enumeration.fields_by_name.put_unique(type_enum_field->name, type_enum_field);
2729 // A user-specified value is available2737 if (field_entry != nullptr) {
2730 ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,2738 ErrorMsg *msg = add_node_error(g, field_node,
2731 nullptr, UndefBad);2739 buf_sprintf("duplicate enum field: '%s'", buf_ptr(type_enum_field->name)));
2732 if (type_is_invalid(result->type)) {2740 add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here"));
2733 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;2741 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2734 continue;2742 continue;
2735 }2743 }
27362744
2737 assert(result->special != ConstValSpecialRuntime);2745 AstNode *tag_value = field_node->data.struct_field.value;
2738 assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt);
27392746
2740 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);2747 if (tag_value != nullptr) {
2741 } else {2748 // A user-specified value is available
2742 // No value was explicitly specified: allocate the last value + 12749 ZigValue *result = analyze_const_value(g, scope, tag_value, tag_int_type,
2743 // or, if this is the first element, zero2750 nullptr, UndefBad);
2744 if (last_enum_field != nullptr) {2751 if (type_is_invalid(result->type)) {
2745 bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one);2752 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2753 continue;
2754 }
2755
2756 assert(result->special != ConstValSpecialRuntime);
2757 assert(result->type->id == ZigTypeIdInt || result->type->id == ZigTypeIdComptimeInt);
2758
2759 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
2746 } else {2760 } else {
2747 bigint_init_unsigned(&type_enum_field->value, 0);2761 // No value was explicitly specified: allocate the last value + 1
2762 // or, if this is the first element, zero
2763 if (last_enum_field != nullptr) {
2764 bigint_add(&type_enum_field->value, &last_enum_field->value, &bi_one);
2765 } else {
2766 bigint_init_unsigned(&type_enum_field->value, 0);
2767 }
2768
2769 // Make sure we can represent this number with tag_int_type
2770 if (!bigint_fits_in_bits(&type_enum_field->value,
2771 tag_int_type->size_in_bits,
2772 tag_int_type->data.integral.is_signed)) {
2773 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2774
2775 Buf *val_buf = buf_alloc();
2776 bigint_append_buf(val_buf, &type_enum_field->value, 10);
2777 add_node_error(g, field_node,
2778 buf_sprintf("enumeration value %s too large for type '%s'",
2779 buf_ptr(val_buf), buf_ptr(&tag_int_type->name)));
2780
2781 break;
2782 }
2748 }2783 }
27492784
2750 // Make sure we can represent this number with tag_int_type2785 // Make sure the value is unique
2751 if (!bigint_fits_in_bits(&type_enum_field->value,2786 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
2752 tag_int_type->size_in_bits,2787 if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) {
2753 tag_int_type->data.integral.is_signed)) {
2754 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;2788 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
27552789
2756 Buf *val_buf = buf_alloc();2790 Buf *val_buf = buf_alloc();
2757 bigint_append_buf(val_buf, &type_enum_field->value, 10);2791 bigint_append_buf(val_buf, &type_enum_field->value, 10);
2758 add_node_error(g, field_node,
2759 buf_sprintf("enumeration value %s too large for type '%s'",
2760 buf_ptr(val_buf), buf_ptr(&tag_int_type->name)));
27612792
2762 break;2793 ErrorMsg *msg = add_node_error(g, field_node,
2794 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
2795 add_error_note(g, msg, entry->value,
2796 buf_sprintf("other occurrence here"));
2763 }2797 }
2764 }
2765
2766 // Make sure the value is unique
2767 auto entry = occupied_tag_values.put_unique(type_enum_field->value, field_node);
2768 if (entry != nullptr && enum_type->data.enumeration.layout != ContainerLayoutExtern) {
2769 enum_type->data.enumeration.resolve_status = ResolveStatusInvalid;
2770
2771 Buf *val_buf = buf_alloc();
2772 bigint_append_buf(val_buf, &type_enum_field->value, 10);
27732798
2774 ErrorMsg *msg = add_node_error(g, field_node,2799 last_enum_field = type_enum_field;
2775 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
2776 add_error_note(g, msg, entry->value,
2777 buf_sprintf("other occurrence here"));
2778 }2800 }
27792801 occupied_tag_values.deinit();
2780 last_enum_field = type_enum_field;
2781 }2802 }
27822803
2783 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)2804 if (enum_type->data.enumeration.resolve_status == ResolveStatusInvalid)
...@@ -2786,8 +2807,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2786,8 +2807,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2786 enum_type->data.enumeration.resolve_loop_flag = false;2807 enum_type->data.enumeration.resolve_loop_flag = false;
2787 enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;2808 enum_type->data.enumeration.resolve_status = ResolveStatusSizeKnown;
27882809
2789 occupied_tag_values.deinit();
2790
2791 return ErrorNone;2810 return ErrorNone;
2792}2811}
27932812
src/ir.cpp+69-1
...@@ -26273,7 +26273,75 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI...@@ -26273,7 +26273,75 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInst *source_instr, ZigTypeI
2627326273
26274 return entry;26274 return entry;
26275 }26275 }
26276 case ZigTypeIdEnum:26276 case ZigTypeIdEnum: {
26277 assert(payload->special == ConstValSpecialStatic);
26278 assert(payload->type == ir_type_info_get_type(ira, "Enum", nullptr));
26279
26280 ZigValue *layout_value = get_const_field(ira, source_instr->source_node, payload, "layout", 0);
26281 assert(layout_value->special == ConstValSpecialStatic);
26282 assert(layout_value->type == ir_type_info_get_type(ira, "ContainerLayout", nullptr));
26283 ContainerLayout layout = (ContainerLayout)bigint_as_u32(&layout_value->data.x_enum_tag);
26284
26285 ZigType *tag_type = get_const_field_meta_type(ira, source_instr->source_node, payload, "tag_type", 1);
26286
26287 ZigValue *fields_value = get_const_field(ira, source_instr->source_node, payload, "fields", 2);
26288 assert(fields_value->special == ConstValSpecialStatic);
26289 assert(is_slice(fields_value->type));
26290 ZigValue *fields_ptr = fields_value->data.x_struct.fields[slice_ptr_index];
26291 ZigValue *fields_len_value = fields_value->data.x_struct.fields[slice_len_index];
26292 size_t fields_len = bigint_as_usize(&fields_len_value->data.x_bigint);
26293
26294 ZigValue *decls_value = get_const_field(ira, source_instr->source_node, payload, "decls", 3);
26295 assert(decls_value->special == ConstValSpecialStatic);
26296 assert(is_slice(decls_value->type));
26297 ZigValue *decls_len_value = decls_value->data.x_struct.fields[slice_len_index];
26298 size_t decls_len = bigint_as_usize(&decls_len_value->data.x_bigint);
26299 if (decls_len != 0) {
26300 ir_add_error(ira, source_instr, buf_create_from_str("TypeInfo.Enum.decls must be empty for @Type"));
26301 return ira->codegen->invalid_inst_gen->value->type;
26302 }
26303
26304 Error err;
26305 bool is_exhaustive;
26306 if ((err = get_const_field_bool(ira, source_instr->source_node, payload, "is_exhaustive", 4, &is_exhaustive)))
26307 return ira->codegen->invalid_inst_gen->value->type;
26308
26309 ZigType *entry = new_type_table_entry(ZigTypeIdEnum);
26310 buf_init_from_buf(&entry->name,
26311 get_anon_type_name(ira->codegen, ira->old_irb.exec, "enum", source_instr->scope, source_instr->source_node, &entry->name));
26312 entry->data.enumeration.decl_node = source_instr->source_node;
26313 entry->data.enumeration.tag_int_type = tag_type;
26314 entry->data.enumeration.decls_scope = create_decls_scope(
26315 ira->codegen, source_instr->source_node, source_instr->scope, entry, get_scope_import(source_instr->scope), &entry->name);
26316 entry->data.enumeration.fields = heap::c_allocator.allocate<TypeEnumField>(fields_len);
26317 entry->data.enumeration.fields_by_name.init(fields_len);
26318 entry->data.enumeration.src_field_count = fields_len;
26319 entry->data.enumeration.layout = layout;
26320 entry->data.enumeration.non_exhaustive = !is_exhaustive;
26321
26322 assert(fields_ptr->data.x_ptr.special == ConstPtrSpecialBaseArray);
26323 assert(fields_ptr->data.x_ptr.data.base_array.elem_index == 0);
26324 ZigValue *fields_arr = fields_ptr->data.x_ptr.data.base_array.array_val;
26325 assert(fields_arr->special == ConstValSpecialStatic);
26326 assert(fields_arr->data.x_array.special == ConstArraySpecialNone);
26327 for (size_t i = 0; i < fields_len; i++) {
26328 ZigValue *field_value = &fields_arr->data.x_array.data.s_none.elements[i];
26329 assert(field_value->type == ir_type_info_get_type(ira, "EnumField", nullptr));
26330 TypeEnumField *field = &entry->data.enumeration.fields[i];
26331 field->name = buf_alloc();
26332 if ((err = get_const_field_buf(ira, source_instr->source_node, field_value, "name", 0, field->name)))
26333 return ira->codegen->invalid_inst_gen->value->type;
26334 field->decl_index = i;
26335 field->decl_node = source_instr->source_node;
26336 if (entry->data.enumeration.fields_by_name.put_unique(field->name, field) != nullptr) {
26337 ir_add_error(ira, source_instr, buf_sprintf("duplicate enum field '%s'", buf_ptr(field->name)));
26338 return ira->codegen->invalid_inst_gen->value->type;
26339 }
26340 field->value = *get_const_field_lit_int(ira, source_instr->source_node, field_value, "value", 1);
26341 }
26342
26343 return entry;
26344 }
26277 case ZigTypeIdUnion:26345 case ZigTypeIdUnion:
26278 ir_add_error(ira, source_instr, buf_sprintf(26346 ir_add_error(ira, source_instr, buf_sprintf(
26279 "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));26347 "TODO implement @Type for 'TypeInfo.%s': see https://github.com/ziglang/zig/issues/2907", type_id_name(tagTypeId)));
test/compile_errors.zig+18-11
...@@ -2,6 +2,22 @@ const tests = @import("tests.zig");...@@ -2,6 +2,22 @@ const tests = @import("tests.zig");
2const std = @import("std");2const std = @import("std");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add("struct with declarations unavailable for @Type",
6 \\export fn entry() void {
7 \\ _ = @Type(@typeInfo(struct { const foo = 1; }));
8 \\}
9 , &[_][]const u8{
10 "tmp.zig:2:15: error: TypeInfo.Struct.decls must be empty for @Type",
11 });
12
13 cases.add("enum with declarations unavailable for @Type",
14 \\export fn entry() void {
15 \\ _ = @Type(@typeInfo(enum { foo, const bar = 1; }));
16 \\}
17 , &[_][]const u8{
18 "tmp.zig:2:15: error: TypeInfo.Enum.decls must be empty for @Type",
19 });
20
5 cases.addTest("reject extern variables with initializers",21 cases.addTest("reject extern variables with initializers",
6 \\extern var foo: int = 2;22 \\extern var foo: int = 2;
7 , &[_][]const u8{23 , &[_][]const u8{
...@@ -598,8 +614,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -598,8 +614,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
598 \\ _ = C;614 \\ _ = C;
599 \\}615 \\}
600 , &[_][]const u8{616 , &[_][]const u8{
601 "tmp.zig:4:5: error: non-exhaustive enum must specify size",617 "tmp.zig:4:5: error: value assigned to '_' field of non-exhaustive enum",
602 "error: value assigned to '_' field of non-exhaustive enum",618 "error: non-exhaustive enum must specify size",
603 "error: non-exhaustive enum specifies every value",619 "error: non-exhaustive enum specifies every value",
604 "error: '_' field of non-exhaustive enum must be last",620 "error: '_' field of non-exhaustive enum must be last",
605 });621 });
...@@ -1400,15 +1416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1400,15 +1416,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1400 , &[_][]const u8{1416 , &[_][]const u8{
1401 "tmp.zig:3:36: error: expected type 'std.builtin.TypeInfo', found 'std.builtin.Int'",1417 "tmp.zig:3:36: error: expected type 'std.builtin.TypeInfo', found 'std.builtin.Int'",
1402 });1418 });
1403
1404 cases.add("struct with declarations unavailable for @Type",
1405 \\export fn entry() void {
1406 \\ _ = @Type(@typeInfo(struct { const foo = 1; }));
1407 \\}
1408 , &[_][]const u8{
1409 "tmp.zig:2:15: error: TypeInfo.Struct.decls must be empty for @Type",
1410 });
1411
1412 cases.add("wrong type for argument tuple to @asyncCall",1419 cases.add("wrong type for argument tuple to @asyncCall",
1413 \\export fn entry1() void {1420 \\export fn entry1() void {
1414 \\ var frame: @Frame(foo) = undefined;1421 \\ var frame: @Frame(foo) = undefined;
test/stage1/behavior/type.zig+34
...@@ -280,3 +280,37 @@ test "Type.Struct" {...@@ -280,3 +280,37 @@ test "Type.Struct" {
280 testing.expectEqual(@as(usize, 0), infoC.decls.len);280 testing.expectEqual(@as(usize, 0), infoC.decls.len);
281 testing.expectEqual(@as(bool, false), infoC.is_tuple);281 testing.expectEqual(@as(bool, false), infoC.is_tuple);
282}282}
283
284test "Type.Enum" {
285 const Foo = @Type(.{
286 .Enum = .{
287 .layout = .Auto,
288 .tag_type = u8,
289 .fields = &[_]TypeInfo.EnumField{
290 .{ .name = "a", .value = 1 },
291 .{ .name = "b", .value = 5 },
292 },
293 .decls = &[_]TypeInfo.Declaration{},
294 .is_exhaustive = true,
295 },
296 });
297 testing.expectEqual(true, @typeInfo(Foo).Enum.is_exhaustive);
298 testing.expectEqual(@as(u8, 1), @enumToInt(Foo.a));
299 testing.expectEqual(@as(u8, 5), @enumToInt(Foo.b));
300 const Bar = @Type(.{
301 .Enum = .{
302 .layout = .Extern,
303 .tag_type = u32,
304 .fields = &[_]TypeInfo.EnumField{
305 .{ .name = "a", .value = 1 },
306 .{ .name = "b", .value = 5 },
307 },
308 .decls = &[_]TypeInfo.Declaration{},
309 .is_exhaustive = false,
310 },
311 });
312 testing.expectEqual(false, @typeInfo(Bar).Enum.is_exhaustive);
313 testing.expectEqual(@as(u32, 1), @enumToInt(Bar.a));
314 testing.expectEqual(@as(u32, 5), @enumToInt(Bar.b));
315 testing.expectEqual(@as(u32, 6), @enumToInt(@intToEnum(Bar, 6)));
316}