mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
stage1: fix non-exhaustive enums with one field
This commit is contained in:
parent
5cb96681d9
commit
65185016f1
@ -7303,7 +7303,14 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
|
||||
case ZigTypeIdEnum:
|
||||
{
|
||||
TypeEnumField *field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum_tag);
|
||||
buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(field->name));
|
||||
if(field != nullptr){
|
||||
buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(field->name));
|
||||
} else {
|
||||
// untagged value in a non-exhaustive enum
|
||||
buf_appendf(buf, "%s.(", buf_ptr(&type_entry->name));
|
||||
bigint_append_buf(buf, &const_val->data.x_enum_tag, 10);
|
||||
buf_appendf(buf, ")");
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ZigTypeIdErrorUnion:
|
||||
|
||||
11
src/ir.cpp
11
src/ir.cpp
@ -14096,7 +14096,8 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I
|
||||
|
||||
// If there is only one possible tag, then we know at comptime what it is.
|
||||
if (enum_type->data.enumeration.layout == ContainerLayoutAuto &&
|
||||
enum_type->data.enumeration.src_field_count == 1)
|
||||
enum_type->data.enumeration.src_field_count == 1 &&
|
||||
!enum_type->data.enumeration.non_exhaustive)
|
||||
{
|
||||
IrInstGen *result = ir_const(ira, source_instr, tag_type);
|
||||
init_const_bigint(result->value, tag_type,
|
||||
@ -14136,7 +14137,8 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr,
|
||||
|
||||
// If there is only 1 possible tag, then we know at comptime what it is.
|
||||
if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
|
||||
wanted_type->data.enumeration.src_field_count == 1)
|
||||
wanted_type->data.enumeration.src_field_count == 1 &&
|
||||
!wanted_type->data.enumeration.non_exhaustive) // TODO are non-exhaustive union tag types supposed to be allowed?
|
||||
{
|
||||
IrInstGen *result = ir_const(ira, source_instr, wanted_type);
|
||||
result->value->special = ConstValSpecialStatic;
|
||||
@ -23814,7 +23816,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||
bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag);
|
||||
return result;
|
||||
}
|
||||
if (tag_type->data.enumeration.src_field_count == 1) {
|
||||
// TODO are non-exhaustive union tag types supposed to be allowed?
|
||||
if (tag_type->data.enumeration.src_field_count == 1 && !tag_type->data.enumeration.non_exhaustive) {
|
||||
IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type);
|
||||
TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];
|
||||
bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
|
||||
@ -23829,7 +23832,7 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||
case ZigTypeIdEnum: {
|
||||
if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
if (target_type->data.enumeration.src_field_count == 1) {
|
||||
if (target_type->data.enumeration.src_field_count == 1 && !target_type->data.enumeration.non_exhaustive) {
|
||||
TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
|
||||
IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type);
|
||||
bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
|
||||
|
||||
@ -85,6 +85,43 @@ test "empty non-exhaustive enum" {
|
||||
comptime S.doTheTest(42);
|
||||
}
|
||||
|
||||
test "single field non-exhaustive enum" {
|
||||
const S = struct {
|
||||
const E = enum(u8) {
|
||||
a,
|
||||
_,
|
||||
};
|
||||
fn doTheTest(y: u8) void {
|
||||
var e: E = .a;
|
||||
expect(switch (e) {
|
||||
.a => true,
|
||||
_ => false,
|
||||
});
|
||||
e = @intToEnum(E, 12);
|
||||
expect(switch (e) {
|
||||
.a => false,
|
||||
_ => true,
|
||||
});
|
||||
|
||||
expect(switch (e) {
|
||||
.a => false,
|
||||
else => true,
|
||||
});
|
||||
e = .a;
|
||||
expect(switch (e) {
|
||||
.a => true,
|
||||
else => false,
|
||||
});
|
||||
|
||||
expect(@enumToInt(@intToEnum(E, y)) == y);
|
||||
expect(@typeInfo(E).Enum.fields.len == 1);
|
||||
expect(@typeInfo(E).Enum.is_exhaustive == false);
|
||||
}
|
||||
};
|
||||
S.doTheTest(23);
|
||||
comptime S.doTheTest(23);
|
||||
}
|
||||
|
||||
test "enum type" {
|
||||
const foo1 = Foo{ .One = 13 };
|
||||
const foo2 = Foo{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user