| ... | ... | @@ -5380,12 +5380,61 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, |
| 5380 | 5380 | return ir_build_const_type(irb, parent_scope, node, container_type); |
| 5381 | 5381 | } |
| 5382 | 5382 | |
| 5383 | // errors should be populated with set1's values |
| 5384 | static TypeTableEntry *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, TypeTableEntry *set1, TypeTableEntry *set2) { |
| 5385 | assert(set1->id == TypeTableEntryIdErrorSet); |
| 5386 | assert(set2->id == TypeTableEntryIdErrorSet); |
| 5387 | |
| 5388 | TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet); |
| 5389 | buf_resize(&err_set_type->name, 0); |
| 5390 | buf_appendf(&err_set_type->name, "error{"); |
| 5391 | |
| 5392 | uint32_t count = set1->data.error_set.err_count; |
| 5393 | for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) { |
| 5394 | ErrorTableEntry *error_entry = set2->data.error_set.errors[i]; |
| 5395 | if (errors[error_entry->value] == nullptr) { |
| 5396 | count += 1; |
| 5397 | } |
| 5398 | } |
| 5399 | |
| 5400 | err_set_type->is_copyable = true; |
| 5401 | err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; |
| 5402 | err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type; |
| 5403 | err_set_type->data.error_set.err_count = count; |
| 5404 | err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(count); |
| 5405 | |
| 5406 | for (uint32_t i = 0; i < set1->data.error_set.err_count; i += 1) { |
| 5407 | ErrorTableEntry *error_entry = set1->data.error_set.errors[i]; |
| 5408 | buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name)); |
| 5409 | err_set_type->data.error_set.errors[i] = error_entry; |
| 5410 | } |
| 5411 | |
| 5412 | uint32_t index = set1->data.error_set.err_count; |
| 5413 | for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) { |
| 5414 | ErrorTableEntry *error_entry = set2->data.error_set.errors[i]; |
| 5415 | if (errors[error_entry->value] == nullptr) { |
| 5416 | errors[error_entry->value] = error_entry; |
| 5417 | buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name)); |
| 5418 | err_set_type->data.error_set.errors[index] = error_entry; |
| 5419 | index += 1; |
| 5420 | } |
| 5421 | } |
| 5422 | assert(index == count); |
| 5423 | |
| 5424 | buf_appendf(&err_set_type->name, "}"); |
| 5425 | |
| 5426 | g->error_di_types.append(&err_set_type->di_type); |
| 5427 | |
| 5428 | return err_set_type; |
| 5429 | |
| 5430 | } |
| 5431 | |
| 5383 | 5432 | static TypeTableEntry *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstNode *node, |
| 5384 | 5433 | ErrorTableEntry *err_entry) |
| 5385 | 5434 | { |
| 5386 | 5435 | TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet); |
| 5387 | 5436 | buf_resize(&err_set_type->name, 0); |
| 5388 | | buf_appendf(&err_set_type->name, "@typeOf(error.%s)", buf_ptr(&err_entry->name)); |
| 5437 | buf_appendf(&err_set_type->name, "error{%s}", buf_ptr(&err_entry->name)); |
| 5389 | 5438 | err_set_type->is_copyable = true; |
| 5390 | 5439 | err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; |
| 5391 | 5440 | err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type; |
| ... | ... | @@ -6656,7 +6705,6 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6656 | 6705 | } |
| 6657 | 6706 | // if err_set_type is a superset of cur_type, keep err_set_type. |
| 6658 | 6707 | // if cur_type is a superset of err_set_type, switch err_set_type to cur_type |
| 6659 | | // otherwise emit a compile error |
| 6660 | 6708 | bool prev_is_superset = true; |
| 6661 | 6709 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { |
| 6662 | 6710 | ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i]; |
| ... | ... | @@ -6689,12 +6737,16 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6689 | 6737 | } |
| 6690 | 6738 | } |
| 6691 | 6739 | if (cur_is_superset) { |
| 6692 | | err_set_type = cur_inst->value.type; |
| 6740 | err_set_type = cur_type; |
| 6693 | 6741 | prev_inst = cur_inst; |
| 6694 | 6742 | continue; |
| 6695 | 6743 | } |
| 6744 | |
| 6745 | // neither of them are supersets. so we invent a new error set type that is a union of both of them |
| 6746 | err_set_type = get_error_set_union(ira->codegen, errors, cur_type, err_set_type); |
| 6747 | continue; |
| 6696 | 6748 | } else if (cur_type->id == TypeTableEntryIdErrorUnion) { |
| 6697 | | // err_set_type must be a subset of cur_type's error set |
| 6749 | // test if err_set_type is a subset of cur_type's error set |
| 6698 | 6750 | // unset everything in errors |
| 6699 | 6751 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { |
| 6700 | 6752 | ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i]; |
| ... | ... | @@ -6719,6 +6771,11 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6719 | 6771 | prev_inst = cur_inst; |
| 6720 | 6772 | continue; |
| 6721 | 6773 | } |
| 6774 | |
| 6775 | // not a subset. invent new error set type, union of both of them |
| 6776 | err_set_type = get_error_set_union(ira->codegen, errors, cur_err_set_type, err_set_type); |
| 6777 | prev_inst = cur_inst; |
| 6778 | continue; |
| 6722 | 6779 | } else { |
| 6723 | 6780 | prev_inst = cur_inst; |
| 6724 | 6781 | continue; |
| ... | ... | @@ -6746,7 +6803,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6746 | 6803 | continue; |
| 6747 | 6804 | } |
| 6748 | 6805 | if (prev_type->id == TypeTableEntryIdErrorUnion) { |
| 6749 | | // the cur type error set must be a subset |
| 6806 | // check if the cur type error set must be a subset |
| 6750 | 6807 | bool prev_is_superset = true; |
| 6751 | 6808 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { |
| 6752 | 6809 | ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i]; |
| ... | ... | @@ -6759,6 +6816,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6759 | 6816 | if (prev_is_superset) { |
| 6760 | 6817 | continue; |
| 6761 | 6818 | } |
| 6819 | // not a subset. invent new error set type, union of both of them |
| 6820 | err_set_type = get_error_set_union(ira->codegen, errors, err_set_type, cur_type); |
| 6821 | continue; |
| 6762 | 6822 | } |
| 6763 | 6823 | } |
| 6764 | 6824 | |
| ... | ... | @@ -6927,21 +6987,25 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6927 | 6987 | } else { |
| 6928 | 6988 | return slice_type; |
| 6929 | 6989 | } |
| 6930 | | } else if (err_set_type != nullptr && prev_inst->value.type->id != TypeTableEntryIdErrorSet) { |
| 6931 | | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || |
| 6932 | | prev_inst->value.type->id == TypeTableEntryIdNumLitFloat) |
| 6933 | | { |
| 6934 | | ir_add_error_node(ira, source_node, |
| 6935 | | buf_sprintf("unable to make error union out of number literal")); |
| 6936 | | return ira->codegen->builtin_types.entry_invalid; |
| 6937 | | } else if (prev_inst->value.type->id == TypeTableEntryIdNullLit) { |
| 6938 | | ir_add_error_node(ira, source_node, |
| 6939 | | buf_sprintf("unable to make error union out of null literal")); |
| 6940 | | return ira->codegen->builtin_types.entry_invalid; |
| 6941 | | } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) { |
| 6942 | | return prev_inst->value.type; |
| 6990 | } else if (err_set_type != nullptr) { |
| 6991 | if (prev_inst->value.type->id == TypeTableEntryIdErrorSet) { |
| 6992 | return err_set_type; |
| 6943 | 6993 | } else { |
| 6944 | | return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type); |
| 6994 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || |
| 6995 | prev_inst->value.type->id == TypeTableEntryIdNumLitFloat) |
| 6996 | { |
| 6997 | ir_add_error_node(ira, source_node, |
| 6998 | buf_sprintf("unable to make error union out of number literal")); |
| 6999 | return ira->codegen->builtin_types.entry_invalid; |
| 7000 | } else if (prev_inst->value.type->id == TypeTableEntryIdNullLit) { |
| 7001 | ir_add_error_node(ira, source_node, |
| 7002 | buf_sprintf("unable to make error union out of null literal")); |
| 7003 | return ira->codegen->builtin_types.entry_invalid; |
| 7004 | } else if (prev_inst->value.type->id == TypeTableEntryIdErrorUnion) { |
| 7005 | return prev_inst->value.type; |
| 7006 | } else { |
| 7007 | return get_error_union_type(ira->codegen, err_set_type, prev_inst->value.type); |
| 7008 | } |
| 6945 | 7009 | } |
| 6946 | 7010 | } else if (any_are_null && prev_inst->value.type->id != TypeTableEntryIdNullLit) { |
| 6947 | 7011 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || |