authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-28 16:27:31+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-04-28 16:27:31+02:00
log2fc34eaa581cc31827e978fbd973bf36d2c647e2
treed4123e07f42b89ee8fe829066bbca0cdaff514a0
parent3178528335cb5efbf237cecb9ea9eb3bfa31b21f

Functions with infered error set can now return literals

fixes #852

3 files changed, 58 insertions(+), 18 deletions(-)

src/analyze.cpp-1
...@@ -6131,4 +6131,3 @@ bool type_can_fail(TypeTableEntry *type_entry) {...@@ -6131,4 +6131,3 @@ bool type_can_fail(TypeTableEntry *type_entry) {
6131bool fn_type_can_fail(FnTypeId *fn_type_id) {6131bool fn_type_can_fail(FnTypeId *fn_type_id) {
6132 return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync;6132 return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync;
6133}6133}
6134
src/ir.cpp+19-17
...@@ -8111,7 +8111,7 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *...@@ -8111,7 +8111,7 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
8111 *errors = reallocate(*errors, old_errors_count, *errors_count);8111 *errors = reallocate(*errors, old_errors_count, *errors_count);
8112}8112}
81138113
8114static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) {8114static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, TypeTableEntry *expected_type, IrInstruction **instructions, size_t instruction_count) {
8115 assert(instruction_count >= 1);8115 assert(instruction_count >= 1);
8116 IrInstruction *prev_inst = instructions[0];8116 IrInstruction *prev_inst = instructions[0];
8117 if (type_is_invalid(prev_inst->value.type)) {8117 if (type_is_invalid(prev_inst->value.type)) {
...@@ -8158,16 +8158,6 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -8158,16 +8158,6 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
8158 continue;8158 continue;
8159 }8159 }
81608160
8161 if (prev_type->id == TypeTableEntryIdNullLit) {
8162 prev_inst = cur_inst;
8163 continue;
8164 }
8165
8166 if (cur_type->id == TypeTableEntryIdNullLit) {
8167 any_are_null = true;
8168 continue;
8169 }
8170
8171 if (prev_type->id == TypeTableEntryIdErrorSet) {8161 if (prev_type->id == TypeTableEntryIdErrorSet) {
8172 assert(err_set_type != nullptr);8162 assert(err_set_type != nullptr);
8173 if (cur_type->id == TypeTableEntryIdErrorSet) {8163 if (cur_type->id == TypeTableEntryIdErrorSet) {
...@@ -8427,6 +8417,16 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -8427,6 +8417,16 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
8427 }8417 }
8428 }8418 }
84298419
8420 if (prev_type->id == TypeTableEntryIdNullLit) {
8421 prev_inst = cur_inst;
8422 continue;
8423 }
8424
8425 if (cur_type->id == TypeTableEntryIdNullLit) {
8426 any_are_null = true;
8427 continue;
8428 }
8429
8430 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node).id == ConstCastResultIdOk) {8430 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node).id == ConstCastResultIdOk) {
8431 continue;8431 continue;
8432 }8432 }
...@@ -8610,6 +8610,10 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -8610,6 +8610,10 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
8610 } else if (err_set_type != nullptr) {8610 } else if (err_set_type != nullptr) {
8611 if (prev_inst->value.type->id == TypeTableEntryIdErrorSet) {8611 if (prev_inst->value.type->id == TypeTableEntryIdErrorSet) {
8612 return err_set_type;8612 return err_set_type;
8613 } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) {
8614 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type->data.error_union.payload_type);
8615 } else if (expected_type != nullptr && expected_type->id == TypeTableEntryIdErrorUnion) {
8616 return get_error_union_type(ira->codegen, err_set_type, expected_type->data.error_union.payload_type);
8613 } else {8617 } else {
8614 if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt ||8618 if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt ||
8615 prev_inst->value.type->id == TypeTableEntryIdNumLitFloat)8619 prev_inst->value.type->id == TypeTableEntryIdNumLitFloat)
...@@ -8621,8 +8625,6 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -8621,8 +8625,6 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
8621 ir_add_error_node(ira, source_node,8625 ir_add_error_node(ira, source_node,
8622 buf_sprintf("unable to make error union out of null literal"));8626 buf_sprintf("unable to make error union out of null literal"));
8623 return ira->codegen->builtin_types.entry_invalid;8627 return ira->codegen->builtin_types.entry_invalid;
8624 } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) {
8625 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type->data.error_union.payload_type);
8626 } else {8628 } else {
8627 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type);8629 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type);
8628 }8630 }
...@@ -10645,7 +10647,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -10645,7 +10647,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
10645 }10647 }
1064610648
10647 IrInstruction *instructions[] = {op1, op2};10649 IrInstruction *instructions[] = {op1, op2};
10648 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, source_node, instructions, 2);10650 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, source_node, nullptr, instructions, 2);
10649 if (type_is_invalid(resolved_type))10651 if (type_is_invalid(resolved_type))
10650 return resolved_type;10652 return resolved_type;
10651 type_ensure_zero_bits_known(ira->codegen, resolved_type);10653 type_ensure_zero_bits_known(ira->codegen, resolved_type);
...@@ -11035,7 +11037,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -11035,7 +11037,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
11035 IrInstruction *op1 = bin_op_instruction->op1->other;11037 IrInstruction *op1 = bin_op_instruction->op1->other;
11036 IrInstruction *op2 = bin_op_instruction->op2->other;11038 IrInstruction *op2 = bin_op_instruction->op2->other;
11037 IrInstruction *instructions[] = {op1, op2};11039 IrInstruction *instructions[] = {op1, op2};
11038 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);11040 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, nullptr, instructions, 2);
11039 if (type_is_invalid(resolved_type))11041 if (type_is_invalid(resolved_type))
11040 return resolved_type;11042 return resolved_type;
11041 IrBinOp op_id = bin_op_instruction->op_id;11043 IrBinOp op_id = bin_op_instruction->op_id;
...@@ -13004,7 +13006,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -13004,7 +13006,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
13004 return first_value->value.type;13006 return first_value->value.type;
13005 }13007 }
1300613008
13007 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node,13009 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, nullptr,
13008 new_incoming_values.items, new_incoming_values.length);13010 new_incoming_values.items, new_incoming_values.length);
13009 if (type_is_invalid(resolved_type))13011 if (type_is_invalid(resolved_type))
13010 return resolved_type;13012 return resolved_type;
...@@ -18696,7 +18698,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -18696,7 +18698,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
18696 } else if (ira->src_implicit_return_type_list.length == 0) {18698 } else if (ira->src_implicit_return_type_list.length == 0) {
18697 return codegen->builtin_types.entry_unreachable;18699 return codegen->builtin_types.entry_unreachable;
18698 } else {18700 } else {
18699 return ir_resolve_peer_types(ira, expected_type_source_node, ira->src_implicit_return_type_list.items,18701 return ir_resolve_peer_types(ira, expected_type_source_node, expected_type, ira->src_implicit_return_type_list.items,
18700 ira->src_implicit_return_type_list.length);18702 ira->src_implicit_return_type_list.length);
18701 }18703 }
18702}18704}
test/cases/error.zig+39
...@@ -202,3 +202,42 @@ const Error = error{};...@@ -202,3 +202,42 @@ const Error = error{};
202fn foo3(b: usize) Error!usize {202fn foo3(b: usize) Error!usize {
203 return b;203 return b;
204}204}
205
206
207test "error: Infer error set from literals" {
208 _ = nullLiteral("n") catch |err| handleErrors(err);
209 _ = floatLiteral("n") catch |err| handleErrors(err);
210 _ = intLiteral("n") catch |err| handleErrors(err);
211 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
212 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
213 _ = comptime intLiteral("n") catch |err| handleErrors(err);
214}
215
216fn handleErrors(err: var) noreturn {
217 switch (err) {
218 error.T => {}
219 }
220
221 unreachable;
222}
223
224fn nullLiteral(str: []const u8) !?i64 {
225 if (str[0] == 'n')
226 return null;
227
228 return error.T;
229}
230
231fn floatLiteral(str: []const u8) !?f64 {
232 if (str[0] == 'n')
233 return 1.0;
234
235 return error.T;
236}
237
238fn intLiteral(str: []const u8) !?i64 {
239 if (str[0] == 'n')
240 return 1;
241
242 return error.T;
243}