authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-05 00:05:04-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-05 00:05:04-05:00
log15075d2c3d7e34fe6c75d7072cfa7f4138bf0910
tree4ab6e8d4c4f267c62dd423aefd9eca9547046de1
parent31abef172a4db98c6917ff9de064225c500cb275

error sets - compile error for equality with no common errors


1 files changed, 122 insertions(+), 4 deletions(-)

src/ir.cpp+122-4
...@@ -6491,6 +6491,60 @@ static bool resolve_inferred_error_set(IrAnalyze *ira, TypeTableEntry *err_set_t...@@ -6491,6 +6491,60 @@ static bool resolve_inferred_error_set(IrAnalyze *ira, TypeTableEntry *err_set_t
6491 return true;6491 return true;
6492}6492}
64936493
6494static TypeTableEntry *get_error_set_intersection(IrAnalyze *ira, TypeTableEntry *set1, TypeTableEntry *set2,
6495 AstNode *source_node)
6496{
6497 assert(set1->id == TypeTableEntryIdErrorSet);
6498 assert(set2->id == TypeTableEntryIdErrorSet);
6499
6500 if (!resolve_inferred_error_set(ira, set1, source_node)) {
6501 return ira->codegen->builtin_types.entry_invalid;
6502 }
6503 if (!resolve_inferred_error_set(ira, set2, source_node)) {
6504 return ira->codegen->builtin_types.entry_invalid;
6505 }
6506 if (type_is_global_error_set(set1)) {
6507 return set2;
6508 }
6509 if (type_is_global_error_set(set2)) {
6510 return set1;
6511 }
6512 ErrorTableEntry **errors = allocate<ErrorTableEntry *>(ira->codegen->errors_by_index.length);
6513 for (uint32_t i = 0; i < set1->data.error_set.err_count; i += 1) {
6514 ErrorTableEntry *error_entry = set1->data.error_set.errors[i];
6515 errors[error_entry->value] = error_entry;
6516 }
6517 ZigList<ErrorTableEntry *> intersection_list = {};
6518
6519 TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet);
6520 buf_resize(&err_set_type->name, 0);
6521 buf_appendf(&err_set_type->name, "error{");
6522
6523 for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) {
6524 ErrorTableEntry *error_entry = set2->data.error_set.errors[i];
6525 ErrorTableEntry *existing_entry = errors[error_entry->value];
6526 if (existing_entry != nullptr) {
6527 intersection_list.append(existing_entry);
6528 buf_appendf(&err_set_type->name, "%s,", buf_ptr(&existing_entry->name));
6529 }
6530 }
6531 free(errors);
6532
6533 err_set_type->is_copyable = true;
6534 err_set_type->type_ref = ira->codegen->builtin_types.entry_global_error_set->type_ref;
6535 err_set_type->di_type = ira->codegen->builtin_types.entry_global_error_set->di_type;
6536 err_set_type->data.error_set.err_count = intersection_list.length;
6537 err_set_type->data.error_set.errors = intersection_list.items;
6538 err_set_type->zero_bits = intersection_list.length == 0;
6539
6540 buf_appendf(&err_set_type->name, "}");
6541
6542 ira->codegen->error_di_types.append(&err_set_type->di_type);
6543
6544 return err_set_type;
6545}
6546
6547
6494static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry *expected_type,6548static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry *expected_type,
6495 TypeTableEntry *actual_type, AstNode *source_node)6549 TypeTableEntry *actual_type, AstNode *source_node)
6496{6550{
...@@ -7313,7 +7367,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod...@@ -7313,7 +7367,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
7313 buf_sprintf("unable to make error union out of null literal"));7367 buf_sprintf("unable to make error union out of null literal"));
7314 return ira->codegen->builtin_types.entry_invalid;7368 return ira->codegen->builtin_types.entry_invalid;
7315 } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) {7369 } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) {
7316 return prev_inst->value.type;7370 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type->data.error_union.payload_type);
7317 } else {7371 } else {
7318 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type);7372 return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type);
7319 }7373 }
...@@ -9147,6 +9201,7 @@ static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {...@@ -9147,6 +9201,7 @@ static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
9147static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {9201static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
9148 IrInstruction *op1 = bin_op_instruction->op1->other;9202 IrInstruction *op1 = bin_op_instruction->op1->other;
9149 IrInstruction *op2 = bin_op_instruction->op2->other;9203 IrInstruction *op2 = bin_op_instruction->op2->other;
9204 AstNode *source_node = bin_op_instruction->base.source_node;
91509205
9151 IrBinOp op_id = bin_op_instruction->op_id;9206 IrBinOp op_id = bin_op_instruction->op_id;
9152 bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);9207 bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
...@@ -9179,7 +9234,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -9179,7 +9234,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
9179 }9234 }
91809235
9181 IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope,9236 IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope,
9182 bin_op_instruction->base.source_node, maybe_op);9237 source_node, maybe_op);
9183 is_non_null->value.type = ira->codegen->builtin_types.entry_bool;9238 is_non_null->value.type = ira->codegen->builtin_types.entry_bool;
91849239
9185 if (op_id == IrBinOpCmpEq) {9240 if (op_id == IrBinOpCmpEq) {
...@@ -9190,8 +9245,69 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -9190,8 +9245,69 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
9190 return ira->codegen->builtin_types.entry_bool;9245 return ira->codegen->builtin_types.entry_bool;
9191 }9246 }
91929247
9248 if (op1->value.type->id == TypeTableEntryIdErrorSet && op2->value.type->id == TypeTableEntryIdErrorSet) {
9249 if (!is_equality_cmp) {
9250 ir_add_error_node(ira, source_node, buf_sprintf("operator not allowed for errors"));
9251 return ira->codegen->builtin_types.entry_invalid;
9252 }
9253 TypeTableEntry *intersect_type = get_error_set_intersection(ira, op1->value.type, op2->value.type, source_node);
9254 if (type_is_invalid(intersect_type)) {
9255 return ira->codegen->builtin_types.entry_invalid;
9256 }
9257
9258 if (!resolve_inferred_error_set(ira, intersect_type, source_node)) {
9259 return ira->codegen->builtin_types.entry_invalid;
9260 }
9261
9262 if (!type_is_global_error_set(intersect_type)) {
9263 if (intersect_type->data.error_set.err_count == 0) {
9264 ir_add_error_node(ira, source_node,
9265 buf_sprintf("error sets '%s' and '%s' have no common errors",
9266 buf_ptr(&op1->value.type->name), buf_ptr(&op2->value.type->name)));
9267 return ira->codegen->builtin_types.entry_invalid;
9268 }
9269 if (op1->value.type->data.error_set.err_count == 1 && op2->value.type->data.error_set.err_count == 1) {
9270 bool are_equal = true;
9271 bool answer;
9272 if (op_id == IrBinOpCmpEq) {
9273 answer = are_equal;
9274 } else if (op_id == IrBinOpCmpNotEq) {
9275 answer = !are_equal;
9276 } else {
9277 zig_unreachable();
9278 }
9279 ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
9280 out_val->data.x_bool = answer;
9281 return ira->codegen->builtin_types.entry_bool;
9282 }
9283 }
9284
9285 ConstExprValue *op1_val = &op1->value;
9286 ConstExprValue *op2_val = &op2->value;
9287 if (value_is_comptime(op1_val) && value_is_comptime(op2_val)) {
9288 bool answer;
9289 bool are_equal = op1_val->data.x_err_set->value == op2_val->data.x_err_set->value;
9290 if (op_id == IrBinOpCmpEq) {
9291 answer = are_equal;
9292 } else if (op_id == IrBinOpCmpNotEq) {
9293 answer = !are_equal;
9294 } else {
9295 zig_unreachable();
9296 }
9297
9298 ConstExprValue *out_val = ir_build_const_from(ira, &bin_op_instruction->base);
9299 out_val->data.x_bool = answer;
9300 return ira->codegen->builtin_types.entry_bool;
9301 }
9302
9303 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id,
9304 op1, op2, bin_op_instruction->safety_check_on);
9305
9306 return ira->codegen->builtin_types.entry_bool;
9307 }
9308
9193 IrInstruction *instructions[] = {op1, op2};9309 IrInstruction *instructions[] = {op1, op2};
9194 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);9310 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, source_node, instructions, 2);
9195 if (type_is_invalid(resolved_type))9311 if (type_is_invalid(resolved_type))
9196 return resolved_type;9312 return resolved_type;
9197 type_ensure_zero_bits_known(ira->codegen, resolved_type);9313 type_ensure_zero_bits_known(ira->codegen, resolved_type);
...@@ -9199,7 +9315,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -9199,7 +9315,6 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
9199 return resolved_type;9315 return resolved_type;
92009316
92019317
9202 AstNode *source_node = bin_op_instruction->base.source_node;
9203 switch (resolved_type->id) {9318 switch (resolved_type->id) {
9204 case TypeTableEntryIdInvalid:9319 case TypeTableEntryIdInvalid:
9205 zig_unreachable(); // handled above9320 zig_unreachable(); // handled above
...@@ -11347,6 +11462,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -11347,6 +11462,9 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
11347 IrInstruction *branch_instruction = predecessor->instruction_list.pop();11462 IrInstruction *branch_instruction = predecessor->instruction_list.pop();
11348 ir_set_cursor_at_end(&ira->new_irb, predecessor);11463 ir_set_cursor_at_end(&ira->new_irb, predecessor);
11349 IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type);11464 IrInstruction *casted_value = ir_implicit_cast(ira, new_value, resolved_type);
11465 if (casted_value == ira->codegen->invalid_instruction) {
11466 return ira->codegen->builtin_types.entry_invalid;
11467 }
11350 new_incoming_values.items[i] = casted_value;11468 new_incoming_values.items[i] = casted_value;
11351 predecessor->instruction_list.append(branch_instruction);11469 predecessor->instruction_list.append(branch_instruction);
1135211470