error set casting building

master
Andrew Kelley 2018-02-08 11:09:18 -05:00
parent 76239f2089
commit fee875770c
4 changed files with 29 additions and 39 deletions

1
TODO
View File

@ -19,6 +19,7 @@ foo() catch |err| switch (err) {};
// TODO this is an explicit cast and should actually coerce the type // TODO this is an explicit cast and should actually coerce the type
erorr set casting erorr set casting
// add a runtime safety check
test err should be comptime if error set has 0 members test err should be comptime if error set has 0 members

View File

@ -560,6 +560,7 @@ enum CastOp {
CastOpResizeSlice, CastOpResizeSlice,
CastOpBytesToSlice, CastOpBytesToSlice,
CastOpNumLitToConcrete, CastOpNumLitToConcrete,
CastOpErrSet,
}; };
struct AstNodeFnCallExpr { struct AstNodeFnCallExpr {

View File

@ -2081,6 +2081,9 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
assert(wanted_type->id == TypeTableEntryIdInt); assert(wanted_type->id == TypeTableEntryIdInt);
assert(actual_type->id == TypeTableEntryIdBool); assert(actual_type->id == TypeTableEntryIdBool);
return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, "");
case CastOpErrSet:
// TODO runtime safety for error casting
return expr_val;
} }
zig_unreachable(); zig_unreachable();
} }

View File

@ -7584,6 +7584,8 @@ static void eval_const_expr_implicit_cast(CastOp cast_op,
switch (cast_op) { switch (cast_op) {
case CastOpNoCast: case CastOpNoCast:
zig_unreachable(); zig_unreachable();
case CastOpErrSet:
zig_panic("TODO");
case CastOpNoop: case CastOpNoop:
{ {
copy_const_val(const_val, other_val, other_val->special == ConstValSpecialStatic); copy_const_val(const_val, other_val, other_val->special == ConstValSpecialStatic);
@ -8039,53 +8041,36 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
return result; return result;
} }
// TODO this is an explicit cast and should actually coerce the type
static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
TypeTableEntry *wanted_type) TypeTableEntry *wanted_type)
{ {
TypeTableEntry *contained_set = value->value.type; assert(value->value.type->id == TypeTableEntryIdErrorSet);
TypeTableEntry *container_set = wanted_type; assert(wanted_type->id == TypeTableEntryIdErrorSet);
assert(contained_set->id == TypeTableEntryIdErrorSet);
assert(container_set->id == TypeTableEntryIdErrorSet);
zig_panic("TODO explicit error set cast");
if (container_set->data.error_set.infer_fn == nullptr &&
!type_is_global_error_set(container_set))
{
ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
for (uint32_t i = 0; i < container_set->data.error_set.err_count; i += 1) {
ErrorTableEntry *error_entry = container_set->data.error_set.errors[i];
assert(errors[error_entry->value] == nullptr);
errors[error_entry->value] = error_entry;
}
ErrorMsg *err_msg = nullptr;
for (uint32_t i = 0; i < contained_set->data.error_set.err_count; i += 1) {
ErrorTableEntry *contained_error_entry = contained_set->data.error_set.errors[i];
ErrorTableEntry *error_entry = errors[contained_error_entry->value];
if (error_entry == nullptr) {
if (err_msg == nullptr) {
err_msg = ir_add_error(ira, source_instr,
buf_sprintf("invalid cast of error set '%s' to error set '%s'",
buf_ptr(&contained_set->name), buf_ptr(&container_set->name)));
}
add_error_note(ira->codegen, err_msg, contained_error_entry->decl_node,
buf_sprintf("'%s.%s' not present in '%s'", buf_ptr(&contained_set->name),
buf_ptr(&contained_error_entry->name), buf_ptr(&container_set->name)));
}
}
free(errors);
if (err_msg != nullptr) {
return ira->codegen->invalid_instruction;
}
}
if (instr_is_comptime(value)) { if (instr_is_comptime(value)) {
ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
if (!val) if (!val)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
if (!resolve_inferred_error_set(ira, wanted_type, source_instr->source_node)) {
return ira->codegen->invalid_instruction;
}
if (!type_is_global_error_set(wanted_type)) {
bool subset = false;
for (uint32_t i = 0, count = wanted_type->data.error_set.err_count; i < count; i += 1) {
if (wanted_type->data.error_set.errors[i]->value == val->data.x_err_set->value) {
subset = true;
break;
}
}
if (!subset) {
ir_add_error(ira, source_instr,
buf_sprintf("error.%s not a member of error set '%s'",
buf_ptr(&val->data.x_err_set->name), buf_ptr(&wanted_type->name)));
return ira->codegen->invalid_instruction;
}
}
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
source_instr->scope, source_instr->source_node); source_instr->scope, source_instr->source_node);
const_instruction->base.value.type = wanted_type; const_instruction->base.value.type = wanted_type;
@ -8094,7 +8079,7 @@ static IrInstruction *ir_analyze_err_set_cast(IrAnalyze *ira, IrInstruction *sou
return &const_instruction->base; return &const_instruction->base;
} }
IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, CastOpNoop); IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, source_instr->source_node, wanted_type, value, CastOpErrSet);
result->value.type = wanted_type; result->value.type = wanted_type;
return result; return result;
} }