Commit 65185016f1
Changed files (3)
test
stage1
behavior
src/analyze.cpp
@@ -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:
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);
test/stage1/behavior/enum.zig
@@ -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{