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) {};...@@ -19,6 +19,7 @@ foo() catch |err| switch (err) {};
1919
20// TODO this is an explicit cast and should actually coerce the type20// TODO this is an explicit cast and should actually coerce the type
21 erorr set casting21 erorr set casting
22 // add a runtime safety check
2223
2324
24test err should be comptime if error set has 0 members25test err should be comptime if error set has 0 members
src/all_types.hpp+1
...@@ -560,6 +560,7 @@ enum CastOp {...@@ -560,6 +560,7 @@ enum CastOp {
560 CastOpResizeSlice,560 CastOpResizeSlice,
561 CastOpBytesToSlice,561 CastOpBytesToSlice,
562 CastOpNumLitToConcrete,562 CastOpNumLitToConcrete,
563 CastOpErrSet,
563};564};
564565
565struct AstNodeFnCallExpr {566struct AstNodeFnCallExpr {
src/codegen.cpp+3
...@@ -2081,6 +2081,9 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2081,6 +2081,9 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2081 assert(wanted_type->id == TypeTableEntryIdInt);2081 assert(wanted_type->id == TypeTableEntryIdInt);
2082 assert(actual_type->id == TypeTableEntryIdBool);2082 assert(actual_type->id == TypeTableEntryIdBool);
2083 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");2083 return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
2084 case CastOpErrSet:
2085 // TODO runtime safety for error casting
2086 return expr_val;
2084 }2087 }
2085 zig_unreachable();2088 zig_unreachable();
2086}2089}
src/ir.cpp+23-38
...@@ -7584,6 +7584,8 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -7584,6 +7584,8 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
7584 switch (cast_op) {7584 switch (cast_op) {
7585 case CastOpNoCast:7585 case CastOpNoCast:
7586 zig_unreachable();7586 zig_unreachable();
7587 case CastOpErrSet:
7588 zig_panic("TODO");
7587 case CastOpNoop:7589 case CastOpNoop:
7588 {7590 {
7589 copy_const_val(const_val, other_val, other_val->special == ConstValSpecialStatic);7591 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...@@ -8039,52 +8041,35 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
8039 return result;8041 return result;
8040}8042}
80418043
8042// TODO this is an explicit cast and should actually coerce the type
8043static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,8044static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
8044 TypeTableEntry *wanted_type)8045 TypeTableEntry *wanted_type)
8045{8046{
8046 TypeTableEntry *contained_set = value->value.type;8047 assert(value->value.type->id == TypeTableEntryIdErrorSet);
8047 TypeTableEntry *container_set = wanted_type;8048 assert(wanted_type->id == TypeTableEntryIdErrorSet);
8048
8049 assert(contained_set->id == TypeTableEntryIdErrorSet);
8050 assert(container_set->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 if (!resolve_inferred_error_set(ira, wanted_type, source_instr->source_node)) {
8055 !type_is_global_error_set(container_set))8056 return ira->codegen->invalid_instruction;
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;
8062 }8057 }
8063 ErrorMsg *err_msg = nullptr;8058 if (!type_is_global_error_set(wanted_type)) {
8064 for (uint32_t i = 0; i < contained_set->data.error_set.err_count; i += 1) {8059 bool subset = false;
8065 ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];8060 for (uint32_t i = 0, count = wanted_type->data.error_set.err_count; i < count; i += 1) {
8066 ErrorTableEntry *error_entry = errors[contained_error_entry->value];8061 if (wanted_type->data.error_set.errors[i]->value == val->data.x_err_set->value) {
8067 if (error_entry == nullptr) {8062 subset = true;
8068 if (err_msg == nullptr) {8063 break;
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)));
8072 }8064 }
8073 add_error_note(ira->codegen, err_msg, contained_error_entry->decl_node,8065 }
8074 buf_sprintf("'%s.%s' not present in '%s'", buf_ptr(&contained_set->name),8066 if (!subset) {
8075 buf_ptr(&contained_error_entry->name), buf_ptr(&container_set->name)));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;
8076 }8071 }
8077 }8072 }
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
8089 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,8074 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
8090 source_instr->scope, source_instr->source_node);8075 source_instr->scope, source_instr->source_node);
...@@ -8094,7 +8079,7 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou...@@ -8094,7 +8079,7 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou
8094 return &const_instruction->base;8079 return &const_instruction->base;
8095 }8080 }
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);
8098 result->value.type = wanted_type;8083 result->value.type = wanted_type;
8099 return result;8084 return result;
8100}8085}