authorgravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2020-05-31 19:15:21+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-17 20:45:34+03:00
log65185016f15ca69363113f85537542b0bdebe33f
tree03adcf96a9a905bc7575fe745bfba5681c0f1d8f
parent5cb96681d92e7a410577215ff057e459f10304dc
signature Commit is signed but in an unrecognized format.

stage1: fix non-exhaustive enums with one field


3 files changed, 52 insertions(+), 5 deletions(-)

src/analyze.cpp+8-1
...@@ -7303,7 +7303,14 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {...@@ -7303,7 +7303,14 @@ void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val) {
7303 case ZigTypeIdEnum:7303 case ZigTypeIdEnum:
7304 {7304 {
7305 TypeEnumField *field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum_tag);7305 TypeEnumField *field = find_enum_field_by_tag(type_entry, &const_val->data.x_enum_tag);
7306 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(field->name));7306 if(field != nullptr){
7307 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(field->name));
7308 } else {
7309 // untagged value in a non-exhaustive enum
7310 buf_appendf(buf, "%s.(", buf_ptr(&type_entry->name));
7311 bigint_append_buf(buf, &const_val->data.x_enum_tag, 10);
7312 buf_appendf(buf, ")");
7313 }
7307 return;7314 return;
7308 }7315 }
7309 case ZigTypeIdErrorUnion:7316 case ZigTypeIdErrorUnion:
src/ir.cpp+7-4
...@@ -14096,7 +14096,8 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I...@@ -14096,7 +14096,8 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I
1409614096
14097 // If there is only one possible tag, then we know at comptime what it is.14097 // If there is only one possible tag, then we know at comptime what it is.
14098 if (enum_type->data.enumeration.layout == ContainerLayoutAuto &&14098 if (enum_type->data.enumeration.layout == ContainerLayoutAuto &&
14099 enum_type->data.enumeration.src_field_count == 1)14099 enum_type->data.enumeration.src_field_count == 1 &&
14100 !enum_type->data.enumeration.non_exhaustive)
14100 {14101 {
14101 IrInstGen *result = ir_const(ira, source_instr, tag_type);14102 IrInstGen *result = ir_const(ira, source_instr, tag_type);
14102 init_const_bigint(result->value, tag_type,14103 init_const_bigint(result->value, tag_type,
...@@ -14136,7 +14137,8 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr,...@@ -14136,7 +14137,8 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr,
1413614137
14137 // If there is only 1 possible tag, then we know at comptime what it is.14138 // If there is only 1 possible tag, then we know at comptime what it is.
14138 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&14139 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
14139 wanted_type->data.enumeration.src_field_count == 1)14140 wanted_type->data.enumeration.src_field_count == 1 &&
14141 !wanted_type->data.enumeration.non_exhaustive) // TODO are non-exhaustive union tag types supposed to be allowed?
14140 {14142 {
14141 IrInstGen *result = ir_const(ira, source_instr, wanted_type);14143 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
14142 result->value->special = ConstValSpecialStatic;14144 result->value->special = ConstValSpecialStatic;
...@@ -23814,7 +23816,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -23814,7 +23816,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,
23814 bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag);23816 bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag);
23815 return result;23817 return result;
23816 }23818 }
23817 if (tag_type->data.enumeration.src_field_count == 1) {23819 // TODO are non-exhaustive union tag types supposed to be allowed?
23820 if (tag_type->data.enumeration.src_field_count == 1 && !tag_type->data.enumeration.non_exhaustive) {
23818 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type);23821 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type);
23819 TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];23822 TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];
23820 bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);23823 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,...@@ -23829,7 +23832,7 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,
23829 case ZigTypeIdEnum: {23832 case ZigTypeIdEnum: {
23830 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))23833 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
23831 return ira->codegen->invalid_inst_gen;23834 return ira->codegen->invalid_inst_gen;
23832 if (target_type->data.enumeration.src_field_count == 1) {23835 if (target_type->data.enumeration.src_field_count == 1 && !target_type->data.enumeration.non_exhaustive) {
23833 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];23836 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
23834 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type);23837 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type);
23835 bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);23838 bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
test/stage1/behavior/enum.zig+37
...@@ -85,6 +85,43 @@ test "empty non-exhaustive enum" {...@@ -85,6 +85,43 @@ test "empty non-exhaustive enum" {
85 comptime S.doTheTest(42);85 comptime S.doTheTest(42);
86}86}
8787
88test "single field non-exhaustive enum" {
89 const S = struct {
90 const E = enum(u8) {
91 a,
92 _,
93 };
94 fn doTheTest(y: u8) void {
95 var e: E = .a;
96 expect(switch (e) {
97 .a => true,
98 _ => false,
99 });
100 e = @intToEnum(E, 12);
101 expect(switch (e) {
102 .a => false,
103 _ => true,
104 });
105
106 expect(switch (e) {
107 .a => false,
108 else => true,
109 });
110 e = .a;
111 expect(switch (e) {
112 .a => true,
113 else => false,
114 });
115
116 expect(@enumToInt(@intToEnum(E, y)) == y);
117 expect(@typeInfo(E).Enum.fields.len == 1);
118 expect(@typeInfo(E).Enum.is_exhaustive == false);
119 }
120 };
121 S.doTheTest(23);
122 comptime S.doTheTest(23);
123}
124
88test "enum type" {125test "enum type" {
89 const foo1 = Foo{ .One = 13 };126 const foo1 = Foo{ .One = 13 };
90 const foo2 = Foo{127 const foo2 = Foo{