| ... | @@ -5380,12 +5380,61 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, | ... | @@ -5380,12 +5380,61 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, |
| 5380 | return ir_build_const_type(irb, parent_scope, node, container_type); | 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 | static TypeTableEntry *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstNode *node, | 5432 | static TypeTableEntry *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstNode *node, |
| 5384 | ErrorTableEntry *err_entry) | 5433 | ErrorTableEntry *err_entry) |
| 5385 | { | 5434 | { |
| 5386 | TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet); | 5435 | TypeTableEntry *err_set_type = new_type_table_entry(TypeTableEntryIdErrorSet); |
| 5387 | buf_resize(&err_set_type->name, 0); | 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 | err_set_type->is_copyable = true; | 5438 | err_set_type->is_copyable = true; |
| 5390 | err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; | 5439 | err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; |
| 5391 | err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type; | 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,7 +6705,6 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6656 | } | 6705 | } |
| 6657 | // if err_set_type is a superset of cur_type, keep err_set_type. | 6706 | // if err_set_type is a superset of cur_type, keep err_set_type. |
| 6658 | // if cur_type is a superset of err_set_type, switch err_set_type to cur_type | 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 | bool prev_is_superset = true; | 6708 | bool prev_is_superset = true; |
| 6661 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { | 6709 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { |
| 6662 | ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i]; | 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,12 +6737,16 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6689 | } | 6737 | } |
| 6690 | } | 6738 | } |
| 6691 | if (cur_is_superset) { | 6739 | if (cur_is_superset) { |
| 6692 | err_set_type = cur_inst->value.type; | 6740 | err_set_type = cur_type; |
| 6693 | prev_inst = cur_inst; | 6741 | prev_inst = cur_inst; |
| 6694 | continue; | 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 | } else if (cur_type->id == TypeTableEntryIdErrorUnion) { | 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 | // unset everything in errors | 6750 | // unset everything in errors |
| 6699 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { | 6751 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { |
| 6700 | ErrorTableEntry *error_entry = err_set_type->data.error_set.errors[i]; | 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,6 +6771,11 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6719 | prev_inst = cur_inst; | 6771 | prev_inst = cur_inst; |
| 6720 | continue; | 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 | } else { | 6779 | } else { |
| 6723 | prev_inst = cur_inst; | 6780 | prev_inst = cur_inst; |
| 6724 | continue; | 6781 | continue; |
| ... | @@ -6746,7 +6803,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod | ... | @@ -6746,7 +6803,7 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6746 | continue; | 6803 | continue; |
| 6747 | } | 6804 | } |
| 6748 | if (prev_type->id == TypeTableEntryIdErrorUnion) { | 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 | bool prev_is_superset = true; | 6807 | bool prev_is_superset = true; |
| 6751 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { | 6808 | for (uint32_t i = 0; i < cur_type->data.error_set.err_count; i += 1) { |
| 6752 | ErrorTableEntry *contained_error_entry = cur_type->data.error_set.errors[i]; | 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,6 +6816,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6759 | if (prev_is_superset) { | 6816 | if (prev_is_superset) { |
| 6760 | continue; | 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,21 +6987,25 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod |
| 6927 | } else { | 6987 | } else { |
| 6928 | return slice_type; | 6988 | return slice_type; |
| 6929 | } | 6989 | } |
| 6930 | } else if (err_set_type != nullptr && prev_inst->value.type->id != TypeTableEntryIdErrorSet) { | 6990 | } else if (err_set_type != nullptr) { |
| 6931 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || | 6991 | if (prev_inst->value.type->id == TypeTableEntryIdErrorSet) { |
| 6932 | prev_inst->value.type->id == TypeTableEntryIdNumLitFloat) | 6992 | return err_set_type; |
| 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; | | |
| 6943 | } else { | 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 | } else if (any_are_null && prev_inst->value.type->id != TypeTableEntryIdNullLit) { | 7010 | } else if (any_are_null && prev_inst->value.type->id != TypeTableEntryIdNullLit) { |
| 6947 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || | 7011 | if (prev_inst->value.type->id == TypeTableEntryIdNumLitInt || |