Skip to content

Commit 2fc34ea

Browse files
committed
Functions with infered error set can now return literals
fixes #852
1 parent 3178528 commit 2fc34ea

File tree

3 files changed

+58
-18
lines changed

3 files changed

+58
-18
lines changed

src/analyze.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6131,4 +6131,3 @@ bool type_can_fail(TypeTableEntry *type_entry) {
61316131
bool fn_type_can_fail(FnTypeId *fn_type_id) {
61326132
return type_can_fail(fn_type_id->return_type) || fn_type_id->cc == CallingConventionAsync;
61336133
}
6134-

src/ir.cpp

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8111,7 +8111,7 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
81118111
*errors = reallocate(*errors, old_errors_count, *errors_count);
81128112
}
81138113

8114-
static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) {
8114+
static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, TypeTableEntry *expected_type, IrInstruction **instructions, size_t instruction_count) {
81158115
assert(instruction_count >= 1);
81168116
IrInstruction *prev_inst = instructions[0];
81178117
if (type_is_invalid(prev_inst->value.type)) {
@@ -8158,16 +8158,6 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
81588158
continue;
81598159
}
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-
81718161
if (prev_type->id == TypeTableEntryIdErrorSet) {
81728162
assert(err_set_type != nullptr);
81738163
if (cur_type->id == TypeTableEntryIdErrorSet) {
@@ -8427,6 +8417,16 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
84278417
}
84288418
}
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+
84308430
if (types_match_const_cast_only(ira, prev_type, cur_type, source_node).id == ConstCastResultIdOk) {
84318431
continue;
84328432
}
@@ -8610,6 +8610,10 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
86108610
} else if (err_set_type != nullptr) {
86118611
if (prev_inst->value.type->id == TypeTableEntryIdErrorSet) {
86128612
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);
86138617
} else {
86148618
if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt ||
86158619
prev_inst->value.type->id == TypeTableEntryIdNumLitFloat)
@@ -8621,8 +8625,6 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
86218625
ir_add_error_node(ira, source_node,
86228626
buf_sprintf("unable to make error union out of null literal"));
86238627
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);
86268628
} else {
86278629
return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type);
86288630
}
@@ -10645,7 +10647,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
1064510647
}
1064610648

1064710649
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);
1064910651
if (type_is_invalid(resolved_type))
1065010652
return resolved_type;
1065110653
type_ensure_zero_bits_known(ira->codegen, resolved_type);
@@ -11035,7 +11037,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1103511037
IrInstruction *op1 = bin_op_instruction->op1->other;
1103611038
IrInstruction *op2 = bin_op_instruction->op2->other;
1103711039
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);
1103911041
if (type_is_invalid(resolved_type))
1104011042
return resolved_type;
1104111043
IrBinOp op_id = bin_op_instruction->op_id;
@@ -13004,7 +13006,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
1300413006
return first_value->value.type;
1300513007
}
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,
1300813010
new_incoming_values.items, new_incoming_values.length);
1300913011
if (type_is_invalid(resolved_type))
1301013012
return resolved_type;
@@ -18696,7 +18698,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
1869618698
} else if (ira->src_implicit_return_type_list.length == 0) {
1869718699
return codegen->builtin_types.entry_unreachable;
1869818700
} 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,
1870018702
ira->src_implicit_return_type_list.length);
1870118703
}
1870218704
}

test/cases/error.zig

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,42 @@ const Error = error{};
202202
fn foo3(b: usize) Error!usize {
203203
return b;
204204
}
205+
206+
207+
test "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+
216+
fn handleErrors(err: var) noreturn {
217+
switch (err) {
218+
error.T => {}
219+
}
220+
221+
unreachable;
222+
}
223+
224+
fn nullLiteral(str: []const u8) !?i64 {
225+
if (str[0] == 'n')
226+
return null;
227+
228+
return error.T;
229+
}
230+
231+
fn floatLiteral(str: []const u8) !?f64 {
232+
if (str[0] == 'n')
233+
return 1.0;
234+
235+
return error.T;
236+
}
237+
238+
fn intLiteral(str: []const u8) !?i64 {
239+
if (str[0] == 'n')
240+
return 1;
241+
242+
return error.T;
243+
}

0 commit comments

Comments
 (0)