| ... | @@ -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 | } |
| 6493 | | 6493 | |
| | 6494 | static 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 | |
| 6494 | static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry *expected_type, | 6548 | static 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) { |
| 9147 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { | 9201 | static 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; |
| 9150 | | 9205 | |
| 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 | } |
| 9180 | | 9235 | |
| 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; |
| 9184 | | 9239 | |
| 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 | } |
| 9192 | | 9247 | |
| | 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; |
| 9200 | | 9316 | |
| 9201 | | 9317 | |
| 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 above | 9320 | 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); |
| 11352 | | 11470 | |