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) {
73037303 case ZigTypeIdEnum:
73047304 {
73057305 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 }
73077314 return;
73087315 }
73097316 case ZigTypeIdErrorUnion:
src/ir.cpp+7-4
......@@ -14096,7 +14096,8 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I
1409614096
1409714097 // If there is only one possible tag, then we know at comptime what it is.
1409814098 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)
1410014101 {
1410114102 IrInstGen *result = ir_const(ira, source_instr, tag_type);
1410214103 init_const_bigint(result->value, tag_type,
......@@ -14136,7 +14137,8 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr,
1413614137
1413714138 // If there is only 1 possible tag, then we know at comptime what it is.
1413814139 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?
1414014142 {
1414114143 IrInstGen *result = ir_const(ira, source_instr, wanted_type);
1414214144 result->value->special = ConstValSpecialStatic;
......@@ -23814,7 +23816,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,
2381423816 bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag);
2381523817 return result;
2381623818 }
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) {
2381823821 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type);
2381923822 TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];
2382023823 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,
2382923832 case ZigTypeIdEnum: {
2383023833 if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
2383123834 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) {
2383323836 TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
2383423837 IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type);
2383523838 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" {
8585 comptime S.doTheTest(42);
8686}
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
88125test "enum type" {
89126 const foo1 = Foo{ .One = 13 };
90127 const foo2 = Foo{