zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 756a218e27831a20395cc370fb3d667666dee20d (tree)
parent 3577a80bb67923c0c165bd3c6e57ef3248e1b59c
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Fri,  8 Dec 2017 17:49:14 -0500

add implicit cast from enum tag type of union to const ptr to the union

closes #654

Diffstat:
Msrc/ir.cpp | 34++++++++++++++++++++++++++++++++++
Mtest/cases/union.zig | 14++++++++++++++
2 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/src/ir.cpp b/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); diff --git a/test/cases/union.zig b/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); +} +