authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-08 11:09:18-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-08 11:09:18-05:00
logfee875770cb8c9363219b736f6c03e15cff39b92
tree711c93d3667e264ca69391bc55526e7375d654c5
parent76239f2089bfb03b24dac0dcad21c9c430ad076d

error set casting building


4 files changed, 28 insertions(+), 38 deletions(-)

TODO+1
......@@ -19,6 +19,7 @@ foo() catch |err| switch (err) {};
1919
2020// TODO this is an explicit cast and should actually coerce the type
2121 erorr set casting
22 // add a runtime safety check
2223
2324
2425test err should be comptime if error set has 0 members
src/all_types.hpp+1
......@@ -560,6 +560,7 @@ enum CastOp {
560560 CastOpResizeSlice,
561561 CastOpBytesToSlice,
562562 CastOpNumLitToConcrete,
563 CastOpErrSet,
563564};
564565
565566struct AstNodeFnCallExpr {
src/codegen.cpp+3
......@@ -2081,6 +2081,9 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
20812081 assert(wanted_type->id == TypeTableEntryIdInt);
20822082 assert(actual_type->id == TypeTableEntryIdBool);
20832083 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
2084 case CastOpErrSet:
2085 // TODO runtime safety for error casting
2086 return expr_val;
20842087 }
20852088 zig_unreachable();
20862089}
src/ir.cpp+23-38
......@@ -7584,6 +7584,8 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
75847584 switch (cast_op) {
75857585 case CastOpNoCast:
75867586 zig_unreachable();
7587 case CastOpErrSet:
7588 zig_panic("TODO");
75877589 case CastOpNoop:
75887590 {
75897591 copy_const_val(const_val, other_val, other_val->special == ConstValSpecialStatic);
......@@ -8039,52 +8041,35 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
80398041 return result;
80408042}
80418043
8042// TODO this is an explicit cast and should actually coerce the type
80438044static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
80448045 TypeTableEntry *wanted_type)
80458046{
8046 TypeTableEntry *contained_set = value->value.type;
8047 TypeTableEntry *container_set = wanted_type;
8048
8049 assert(contained_set->id == TypeTableEntryIdErrorSet);
8050 assert(container_set->id == TypeTableEntryIdErrorSet);
8047 assert(value->value.type->id == TypeTableEntryIdErrorSet);
8048 assert(wanted_type->id == TypeTableEntryIdErrorSet);
80518049
8052 zig_panic("TODO explicit error set cast");
8050 if (instr_is_comptime(value)) {
8051 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
8052 if (!val)
8053 return ira->codegen->invalid_instruction;
80538054
8054 if (container_set->data.error_set.infer_fn == nullptr &&
8055 !type_is_global_error_set(container_set))
8056 {
8057 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
8058 for (uint32_t i = 0; i < container_set->data.error_set.err_count; i += 1) {
8059 ErrorTableEntry *error_entry = container_set->data.error_set.errors[i];
8060 assert(errors[error_entry->value] == nullptr);
8061 errors[error_entry->value] = error_entry;
8055 if (!resolve_inferred_error_set(ira, wanted_type, source_instr->source_node)) {
8056 return ira->codegen->invalid_instruction;
80628057 }
8063 ErrorMsg *err_msg = nullptr;
8064 for (uint32_t i = 0; i < contained_set->data.error_set.err_count; i += 1) {
8065 ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];
8066 ErrorTableEntry *error_entry = errors[contained_error_entry->value];
8067 if (error_entry == nullptr) {
8068 if (err_msg == nullptr) {
8069 err_msg = ir_add_error(ira, source_instr,
8070 buf_sprintf("invalid cast of error set '%s' to error set '%s'",
8071 buf_ptr(&contained_set->name), buf_ptr(&container_set->name)));
8058 if (!type_is_global_error_set(wanted_type)) {
8059 bool subset = false;
8060 for (uint32_t i = 0, count = wanted_type->data.error_set.err_count; i < count; i += 1) {
8061 if (wanted_type->data.error_set.errors[i]->value == val->data.x_err_set->value) {
8062 subset = true;
8063 break;
80728064 }
8073 add_error_note(ira->codegen, err_msg, contained_error_entry->decl_node,
8074 buf_sprintf("'%s.%s' not present in '%s'", buf_ptr(&contained_set->name),
8075 buf_ptr(&contained_error_entry->name), buf_ptr(&container_set->name)));
8065 }
8066 if (!subset) {
8067 ir_add_error(ira, source_instr,
8068 buf_sprintf("error.%s not a member of error set '%s'",
8069 buf_ptr(&val->data.x_err_set->name), buf_ptr(&wanted_type->name)));
8070 return ira->codegen->invalid_instruction;
80768071 }
80778072 }
8078 free(errors);
8079 if (err_msg != nullptr) {
8080 return ira->codegen->invalid_instruction;
8081 }
8082 }
8083
8084 if (instr_is_comptime(value)) {
8085 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
8086 if (!val)
8087 return ira->codegen->invalid_instruction;
80888073
80898074 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
80908075 source_instr->scope, source_instr->source_node);
......@@ -8094,7 +8079,7 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou
80948079 return &const_instruction->base;
80958080 }
80968081
8097 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, CastOpNoop);
8082 IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, CastOpErrSet);
80988083 result->value.type = wanted_type;
80998084 return result;
81008085}