stage1: fix non-exhaustive enums with one field

This commit is contained in:
xackus 2020-05-31 19:15:21 +02:00 committed by Vexu
parent 5cb96681d9
commit 65185016f1
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
3 changed files with 52 additions and 5 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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{