aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorTimon Kruiper <timonkruiper@gmail.com>2019-07-11 15:17:35 +0200
committerAndrew Kelley <andrew@ziglang.org>2019-09-04 12:30:23 -0400
commite540e5b8ec1d90b86d6f41814507e6ae4ae5edd8 (patch)
treeabf9d434da52b0439d5fe273fc26cf9302e7c077 /src/ir.cpp
parent53a6aea216d7b1e6b6072d30f2d51ed801d9e0f9 (diff)
downloadzig-e540e5b8ec1d90b86d6f41814507e6ae4ae5edd8.tar.gz
zig-e540e5b8ec1d90b86d6f41814507e6ae4ae5edd8.zip
Implicit cast from enum literal to optional enum and implicit cast to payload of error union
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp61
1 files changed, 47 insertions, 14 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 9547b1ec61..bf0b1188b1 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -12081,6 +12081,29 @@ static bool is_pointery_and_elem_is_not_pointery(ZigType *ty) {
return false;
}
+static IrInstruction *ir_analyze_enum_literal(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
+ ZigType *enum_type)
+{
+ assert(enum_type->id == ZigTypeIdEnum);
+
+ Error err;
+ if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusZeroBitsKnown)))
+ return ira->codegen->invalid_instruction;
+
+ TypeEnumField *field = find_enum_type_field(enum_type, value->value.data.x_enum_literal);
+ if (field == nullptr) {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("enum '%s' has no field named '%s'",
+ buf_ptr(&enum_type->name), buf_ptr(value->value.data.x_enum_literal)));
+ add_error_note(ira->codegen, msg, enum_type->data.enumeration.decl_node,
+ buf_sprintf("'%s' declared here", buf_ptr(&enum_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+ IrInstruction *result = ir_const(ira, source_instr, enum_type);
+ bigint_init_bigint(&result->value.data.x_enum_tag, &field->value);
+
+ return result;
+}
+
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc)
{
@@ -12439,21 +12462,31 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
// cast from enum literal to enum with matching field name
- if (actual_type->id == ZigTypeIdEnumLiteral && wanted_type->id == ZigTypeIdEnum) {
- if ((err = type_resolve(ira->codegen, wanted_type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->invalid_instruction;
+ if (actual_type->id == ZigTypeIdEnumLiteral && wanted_type->id == ZigTypeIdEnum)
+ {
+ return ir_analyze_enum_literal(ira, source_instr, value, wanted_type);
+ }
- TypeEnumField *field = find_enum_type_field(wanted_type, value->value.data.x_enum_literal);
- if (field == nullptr) {
- ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("enum '%s' has no field named '%s'",
- buf_ptr(&wanted_type->name), buf_ptr(value->value.data.x_enum_literal)));
- add_error_note(ira->codegen, msg, wanted_type->data.enumeration.decl_node,
- buf_sprintf("'%s' declared here", buf_ptr(&wanted_type->name)));
- return ira->codegen->invalid_instruction;
- }
- IrInstruction *result = ir_const(ira, source_instr, wanted_type);
- bigint_init_bigint(&result->value.data.x_enum_tag, &field->value);
- return result;
+ // cast from enum literal to optional enum
+ if (actual_type->id == ZigTypeIdEnumLiteral &&
+ (wanted_type->id == ZigTypeIdOptional && wanted_type->data.maybe.child_type->id == ZigTypeIdEnum))
+ {
+ IrInstruction *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.maybe.child_type);
+ if (result == ira->codegen->invalid_instruction)
+ return result;
+
+ return ir_analyze_optional_wrap(ira, result, value, wanted_type, result_loc);
+ }
+
+ // cast from enum literal to error union when payload is an enum
+ if (actual_type->id == ZigTypeIdEnumLiteral &&
+ (wanted_type->id == ZigTypeIdErrorUnion && wanted_type->data.error_union.payload_type->id == ZigTypeIdEnum))
+ {
+ IrInstruction *result = ir_analyze_enum_literal(ira, source_instr, value, wanted_type->data.error_union.payload_type);
+ if (result == ira->codegen->invalid_instruction)
+ return result;
+
+ return ir_analyze_err_wrap_payload(ira, result, value, wanted_type, result_loc);
}
// cast from union to the enum type of the union