authorgravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2019-07-11 15:17:35+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-04 12:30:23-04:00
loge540e5b8ec1d90b86d6f41814507e6ae4ae5edd8
treeabf9d434da52b0439d5fe273fc26cf9302e7c077
parent53a6aea216d7b1e6b6072d30f2d51ed801d9e0f9
signaturelock-open Commit is signed but in an unrecognized format.

Implicit cast from enum literal to optional enum and implicit cast to payload of error union


2 files changed, 61 insertions(+), 14 deletions(-)

src/ir.cpp+47-14
...@@ -12081,6 +12081,29 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) {...@@ -12081,6 +12081,29 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) {
12081 return false;12081 return false;
12082}12082}
1208312083
12084static IrInstruction *ir_analyze_enum_literal(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
12085 ZigType *enum_type)
12086{
12087 assert(enum_type->id == ZigTypeIdEnum);
12088
12089 Error err;
12090 if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusZeroBitsKnown)))
12091 return ira->codegen->invalid_instruction;
12092
12093 TypeEnumField *field = find_enum_type_field(enum_type, value->value.data.x_enum_literal);
12094 if (field == nullptr) {
12095 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("enum '%s' has no field named '%s'",
12096 buf_ptr(&enum_type->name), buf_ptr(value->value.data.x_enum_literal)));
12097 add_error_note(ira->codegen, msg, enum_type->data.enumeration.decl_node,
12098 buf_sprintf("'%s' declared here", buf_ptr(&enum_type->name)));
12099 return ira->codegen->invalid_instruction;
12100 }
12101 IrInstruction *result = ir_const(ira, source_instr, enum_type);
12102 bigint_init_bigint(&result->value.data.x_enum_tag, &field->value);
12103
12104 return result;
12105}
12106
12084static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,12107static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
12085 ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc)12108 ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc)
12086{12109{
...@@ -12439,21 +12462,31 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12439,21 +12462,31 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12439 }12462 }
1244012463
12441 // cast from enum literal to enum with matching field name12464 // cast from enum literal to enum with matching field name
12442 if (actual_type->id == ZigTypeIdEnumLiteral && wanted_type->id == ZigTypeIdEnum) {12465 if (actual_type->id == ZigTypeIdEnumLiteral && wanted_type->id == ZigTypeIdEnum)
12443 if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))12466 {
12444 return ira->codegen->invalid_instruction;12467 return ir_analyze_enum_literal(ira, source_instr, value, wanted_type);
12468 }
1244512469
12446 TypeEnumField *field = find_enum_type_field(wanted_type, value->value.data.x_enum_literal);12470 // cast from enum literal to optional enum
12447 if (field == nullptr) {12471 if (actual_type->id == ZigTypeIdEnumLiteral &&
12448 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("enum '%s' has no field named '%s'",12472 (wanted_type->id == ZigTypeIdOptional && wanted_type->data.maybe.child_type->id == ZigTypeIdEnum))
12449 buf_ptr(&wanted_type->name), buf_ptr(value->value.data.x_enum_literal)));12473 {
12450 add_error_note(ira->codegen, msg, wanted_type->data.enumeration.decl_node,12474 IrInstruction *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.maybe.child_type);
12451 buf_sprintf("'%s' declared here", buf_ptr(&wanted_type->name)));12475 if (result == ira->codegen->invalid_instruction)
12452 return ira->codegen->invalid_instruction;12476 return result;
12453 }12477
12454 IrInstruction *result = ir_const(ira, source_instr, wanted_type);12478 return ir_analyze_optional_wrap(ira, result, value, wanted_type, result_loc);
12455 bigint_init_bigint(&result->value.data.x_enum_tag, &field->value);12479 }
12456 return result;12480
12481 // cast from enum literal to error union when payload is an enum
12482 if (actual_type->id == ZigTypeIdEnumLiteral &&
12483 (wanted_type->id == ZigTypeIdErrorUnion && wanted_type->data.error_union.payload_type->id == ZigTypeIdEnum))
12484 {
12485 IrInstruction *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.error_union.payload_type);
12486 if (result == ira->codegen->invalid_instruction)
12487 return result;
12488
12489 return ir_analyze_err_wrap_payload(ira, result, value, wanted_type, result_loc);
12457 }12490 }
1245812491
12459 // cast from union to the enum type of the union12492 // cast from union to the enum type of the union
test/stage1/behavior/enum.zig+14
...@@ -993,3 +993,17 @@ test "enum with one member and custom tag type" {...@@ -993,3 +993,17 @@ test "enum with one member and custom tag type" {
993 };993 };
994 expect(@enumToInt(E2.One) == 2);994 expect(@enumToInt(E2.One) == 2);
995}995}
996
997test "enum literal casting to optional" {
998 var bar: ?Bar = undefined;
999 bar = .B;
1000
1001 expect(bar.? == Bar.B);
1002}
1003
1004test "enum literal casting to error union with payload enum" {
1005 var bar: error{B}!Bar = undefined;
1006 bar = .B; // should never cast to the error set
1007
1008 expect((try bar) == Bar.B);
1009}