authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-26 12:59:30-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-26 12:59:30-04:00
log21ed9391179a9e472b25c80eaec5eebc9d08aca8
treec25253450faa5b0ce2dbf21f096e759f8ff90abd
parent163a8e98bc04ea955ee54d5905436ffac34c93a2
signaturelock-open Commit is signed but in an unrecognized format.

support enum literals implicit casting to tagged unions


2 files changed, 57 insertions(+), 15 deletions(-)

src/ir.cpp+34-12
......@@ -8993,6 +8993,13 @@ static bool slice_is_const(ZigType *type) {
89938993 return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
89948994}
89958995
8996static bool is_tagged_union(ZigType *type) {
8997 if (type->id != ZigTypeIdUnion)
8998 return false;
8999 return (type->data.unionation.decl_node->data.container_decl.auto_enum ||
9000 type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr);
9001}
9002
89969003static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) {
89979004 assert(set->id == ZigTypeIdErrorSet);
89989005 for (uint32_t i = 0; i < set->data.error_set.err_count; i += 1) {
......@@ -9676,6 +9683,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
96769683 continue;
96779684 }
96789685 }
9686 if (is_tagged_union(prev_type) && cur_type->id == ZigTypeIdEnumLiteral) {
9687 TypeUnionField *field = find_union_type_field(prev_type, cur_inst->value.data.x_enum_literal);
9688 if (field != nullptr) {
9689 continue;
9690 }
9691 }
96799692
96809693 if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdEnumLiteral) {
96819694 TypeEnumField *field = find_enum_type_field(cur_type, prev_inst->value.data.x_enum_literal);
......@@ -9685,6 +9698,14 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
96859698 }
96869699 }
96879700
9701 if (is_tagged_union(cur_type) && prev_type->id == ZigTypeIdEnumLiteral) {
9702 TypeUnionField *field = find_union_type_field(cur_type, prev_inst->value.data.x_enum_literal);
9703 if (field != nullptr) {
9704 prev_inst = cur_inst;
9705 continue;
9706 }
9707 }
9708
96889709 if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
96899710 (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
96909711 {
......@@ -10907,11 +10928,17 @@ static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruc
1090710928}
1090810929
1090910930static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *source_instr,
10910 IrInstruction *target, ZigType *wanted_type)
10931 IrInstruction *uncasted_target, ZigType *wanted_type)
1091110932{
1091210933 Error err;
1091310934 assert(wanted_type->id == ZigTypeIdUnion);
10914 assert(target->value.type->id == ZigTypeIdEnum);
10935
10936 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
10937 return ira->codegen->invalid_instruction;
10938
10939 IrInstruction *target = ir_implicit_cast(ira, uncasted_target, wanted_type->data.unionation.tag_type);
10940 if (type_is_invalid(target->value.type))
10941 return ira->codegen->invalid_instruction;
1091510942
1091610943 if (instr_is_comptime(target)) {
1091710944 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
......@@ -11788,17 +11815,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1178811815 }
1178911816 }
1179011817
11791 // enum to union which has the enum as the tag type
11792 if (wanted_type->id == ZigTypeIdUnion && actual_type->id == ZigTypeIdEnum &&
11793 (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
11794 wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
11818 // enum to union which has the enum as the tag type, or
11819 // enum literal to union which has a matching enum as the tag type
11820 if (is_tagged_union(wanted_type) && (actual_type->id == ZigTypeIdEnum ||
11821 actual_type->id == ZigTypeIdEnumLiteral))
1179511822 {
11796 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
11797 return ira->codegen->invalid_instruction;
11798
11799 if (wanted_type->data.unionation.tag_type == actual_type) {
11800 return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type);
11801 }
11823 return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type);
1180211824 }
1180311825
1180411826 // cast from *T to *[1]T
test/stage1/behavior/enum.zig+23-3
......@@ -930,9 +930,9 @@ test "enum literal in array literal" {
930930 two,
931931 };
932932
933 const array = []Items {
934 .one,
935 .two,
933 const array = []Items{
934 .one,
935 .two,
936936 };
937937
938938 expect(array[0] == .one);
......@@ -962,3 +962,23 @@ test "enum value allocation" {
962962 expect(@enumToInt(LargeEnum.A1) == 0x80000001);
963963 expect(@enumToInt(LargeEnum.A2) == 0x80000002);
964964}
965
966test "enum literal casting to tagged union" {
967 const Arch = union(enum) {
968 x86_64,
969 arm: Arm32,
970
971 const Arm32 = enum {
972 v8_5a,
973 v8_4a,
974 };
975 };
976
977 var t = true;
978 var x: Arch = .x86_64;
979 var y = if (t) x else .x86_64;
980 switch (y) {
981 .x86_64 => {},
982 else => @panic("fail"),
983 }
984}