Commit 756a218e27

Andrew Kelley <superjoe30@gmail.com>
2017-12-08 23:49:14
add implicit cast from enum tag type of union to const ptr to the union
closes #654
1 parent 3577a80
Changed files (2)
src
test
cases
src/ir.cpp
@@ -7492,6 +7492,19 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
         }
     }
 
+    // implicit enum to &const union which has the enum as the tag type
+    if (actual_type->id == TypeTableEntryIdEnum && expected_type->id == TypeTableEntryIdPointer) {
+        TypeTableEntry *union_type = expected_type->data.pointer.child_type;
+        if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
+            union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
+        {
+            type_ensure_zero_bits_known(ira->codegen, union_type);
+            if (union_type->data.unionation.tag_type == actual_type) {
+                return ImplicitCastMatchResultYes;
+            }
+        }
+    }
+
     // implicit undefined literal to anything
     if (actual_type->id == TypeTableEntryIdUndefLit) {
         return ImplicitCastMatchResultYes;
@@ -9079,6 +9092,27 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
         }
     }
 
+    // explicit enum to &const union which has the enum as the tag type
+    if (actual_type->id == TypeTableEntryIdEnum && wanted_type->id == TypeTableEntryIdPointer) {
+        TypeTableEntry *union_type = wanted_type->data.pointer.child_type;
+        if (union_type->data.unionation.decl_node->data.container_decl.auto_enum ||
+            union_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr)
+        {
+            type_ensure_zero_bits_known(ira->codegen, union_type);
+            if (union_type->data.unionation.tag_type == actual_type) {
+                IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, union_type, value);
+                if (type_is_invalid(cast1->value.type))
+                    return ira->codegen->invalid_instruction;
+
+                IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+                if (type_is_invalid(cast2->value.type))
+                    return ira->codegen->invalid_instruction;
+
+                return cast2;
+            }
+        }
+    }
+
     // explicit cast from undefined to anything
     if (actual_type->id == TypeTableEntryIdUndefLit) {
         return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
test/cases/union.zig
@@ -206,3 +206,17 @@ test "implicit cast union to its tag type" {
 fn giveMeLetterB(x: Letter2) {
     assert(x == Value2.B);
 }
+
+test "implicit cast from @EnumTagType(TheUnion) to &const TheUnion" {
+    assertIsTheUnion2Item1(TheUnion2.Item1);
+}
+
+const TheUnion2 = union(enum) {
+    Item1,
+    Item2: i32,
+};
+
+fn assertIsTheUnion2Item1(value: &const TheUnion2) {
+    assert(*value == TheUnion2.Item1);
+}
+