mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 19:23:08 +00:00
support enum literals implicit casting to tagged unions
This commit is contained in:
parent
163a8e98bc
commit
21ed939117
44
src/ir.cpp
44
src/ir.cpp
@ -8993,6 +8993,13 @@ static bool slice_is_const(ZigType *type) {
|
|||||||
return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
|
return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_tagged_union(ZigType *type) {
|
||||||
|
if (type->id != ZigTypeIdUnion)
|
||||||
|
return false;
|
||||||
|
return (type->data.unionation.decl_node->data.container_decl.auto_enum ||
|
||||||
|
type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) {
|
static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) {
|
||||||
assert(set->id == ZigTypeIdErrorSet);
|
assert(set->id == ZigTypeIdErrorSet);
|
||||||
for (uint32_t i = 0; i < set->data.error_set.err_count; i += 1) {
|
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
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_tagged_union(prev_type) && cur_type->id == ZigTypeIdEnumLiteral) {
|
||||||
|
TypeUnionField *field = find_union_type_field(prev_type, cur_inst->value.data.x_enum_literal);
|
||||||
|
if (field != nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdEnumLiteral) {
|
if (cur_type->id == ZigTypeIdEnum && prev_type->id == ZigTypeIdEnumLiteral) {
|
||||||
TypeEnumField *field = find_enum_type_field(cur_type, prev_inst->value.data.x_enum_literal);
|
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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_tagged_union(cur_type) && prev_type->id == ZigTypeIdEnumLiteral) {
|
||||||
|
TypeUnionField *field = find_union_type_field(cur_type, prev_inst->value.data.x_enum_literal);
|
||||||
|
if (field != nullptr) {
|
||||||
|
prev_inst = cur_inst;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
|
if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
|
||||||
(cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
|
(cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
|
||||||
{
|
{
|
||||||
@ -10907,11 +10928,17 @@ static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruc
|
|||||||
}
|
}
|
||||||
|
|
||||||
static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *source_instr,
|
static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *source_instr,
|
||||||
IrInstruction *target, ZigType *wanted_type)
|
IrInstruction *uncasted_target, ZigType *wanted_type)
|
||||||
{
|
{
|
||||||
Error err;
|
Error err;
|
||||||
assert(wanted_type->id == ZigTypeIdUnion);
|
assert(wanted_type->id == ZigTypeIdUnion);
|
||||||
assert(target->value.type->id == ZigTypeIdEnum);
|
|
||||||
|
if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
|
IrInstruction *target = ir_implicit_cast(ira, uncasted_target, wanted_type->data.unionation.tag_type);
|
||||||
|
if (type_is_invalid(target->value.type))
|
||||||
|
return ira->codegen->invalid_instruction;
|
||||||
|
|
||||||
if (instr_is_comptime(target)) {
|
if (instr_is_comptime(target)) {
|
||||||
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
|
ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
|
||||||
@ -11788,18 +11815,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// enum to union which has the enum as the tag type
|
// enum to union which has the enum as the tag type, or
|
||||||
if (wanted_type->id == ZigTypeIdUnion && actual_type->id == ZigTypeIdEnum &&
|
// enum literal to union which has a matching enum as the tag type
|
||||||
(wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
|
if (is_tagged_union(wanted_type) && (actual_type->id == ZigTypeIdEnum ||
|
||||||
wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
|
actual_type->id == ZigTypeIdEnumLiteral))
|
||||||
{
|
{
|
||||||
if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
|
|
||||||
return ira->codegen->invalid_instruction;
|
|
||||||
|
|
||||||
if (wanted_type->data.unionation.tag_type == actual_type) {
|
|
||||||
return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type);
|
return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// cast from *T to *[1]T
|
// cast from *T to *[1]T
|
||||||
if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
|
if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenSingle &&
|
||||||
|
|||||||
@ -930,7 +930,7 @@ test "enum literal in array literal" {
|
|||||||
two,
|
two,
|
||||||
};
|
};
|
||||||
|
|
||||||
const array = []Items {
|
const array = []Items{
|
||||||
.one,
|
.one,
|
||||||
.two,
|
.two,
|
||||||
};
|
};
|
||||||
@ -962,3 +962,23 @@ test "enum value allocation" {
|
|||||||
expect(@enumToInt(LargeEnum.A1) == 0x80000001);
|
expect(@enumToInt(LargeEnum.A1) == 0x80000001);
|
||||||
expect(@enumToInt(LargeEnum.A2) == 0x80000002);
|
expect(@enumToInt(LargeEnum.A2) == 0x80000002);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "enum literal casting to tagged union" {
|
||||||
|
const Arch = union(enum) {
|
||||||
|
x86_64,
|
||||||
|
arm: Arm32,
|
||||||
|
|
||||||
|
const Arm32 = enum {
|
||||||
|
v8_5a,
|
||||||
|
v8_4a,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var t = true;
|
||||||
|
var x: Arch = .x86_64;
|
||||||
|
var y = if (t) x else .x86_64;
|
||||||
|
switch (y) {
|
||||||
|
.x86_64 => {},
|
||||||
|
else => @panic("fail"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user