| ... | @@ -14096,7 +14096,8 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I | ... | @@ -14096,7 +14096,8 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I |
| 14096 | | 14096 | |
| 14097 | // If there is only one possible tag, then we know at comptime what it is. | 14097 | // If there is only one possible tag, then we know at comptime what it is. |
| 14098 | if (enum_type->data.enumeration.layout == ContainerLayoutAuto && | 14098 | if (enum_type->data.enumeration.layout == ContainerLayoutAuto && |
| 14099 | enum_type->data.enumeration.src_field_count == 1) | 14099 | enum_type->data.enumeration.src_field_count == 1 && |
| | 14100 | !enum_type->data.enumeration.non_exhaustive) |
| 14100 | { | 14101 | { |
| 14101 | IrInstGen *result = ir_const(ira, source_instr, tag_type); | 14102 | IrInstGen *result = ir_const(ira, source_instr, tag_type); |
| 14102 | init_const_bigint(result->value, tag_type, | 14103 | init_const_bigint(result->value, tag_type, |
| ... | @@ -14136,7 +14137,8 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -14136,7 +14137,8 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr, |
| 14136 | | 14137 | |
| 14137 | // If there is only 1 possible tag, then we know at comptime what it is. | 14138 | // If there is only 1 possible tag, then we know at comptime what it is. |
| 14138 | if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && | 14139 | if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && |
| 14139 | wanted_type->data.enumeration.src_field_count == 1) | 14140 | wanted_type->data.enumeration.src_field_count == 1 && |
| | 14141 | !wanted_type->data.enumeration.non_exhaustive) |
| 14140 | { | 14142 | { |
| 14141 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); | 14143 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 14142 | result->value->special = ConstValSpecialStatic; | 14144 | result->value->special = ConstValSpecialStatic; |
| ... | @@ -14175,7 +14177,14 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -14175,7 +14177,14 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, |
| 14175 | if (!val) | 14177 | if (!val) |
| 14176 | return ira->codegen->invalid_inst_gen; | 14178 | return ira->codegen->invalid_inst_gen; |
| 14177 | TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag); | 14179 | TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag); |
| 14178 | assert(union_field != nullptr); | 14180 | if (union_field == nullptr) { |
| | 14181 | Buf *int_buf = buf_alloc(); |
| | 14182 | bigint_append_buf(int_buf, &target->value->data.x_enum_tag, 10); |
| | 14183 | |
| | 14184 | ir_add_error(ira, &target->base, |
| | 14185 | buf_sprintf("no tag by value %s", buf_ptr(int_buf))); |
| | 14186 | return ira->codegen->invalid_inst_gen; |
| | 14187 | } |
| 14179 | ZigType *field_type = resolve_union_field_type(ira->codegen, union_field); | 14188 | ZigType *field_type = resolve_union_field_type(ira->codegen, union_field); |
| 14180 | if (field_type == nullptr) | 14189 | if (field_type == nullptr) |
| 14181 | return ira->codegen->invalid_inst_gen; | 14190 | return ira->codegen->invalid_inst_gen; |
| ... | @@ -14211,6 +14220,13 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -14211,6 +14220,13 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, |
| 14211 | return result; | 14220 | return result; |
| 14212 | } | 14221 | } |
| 14213 | | 14222 | |
| | 14223 | if (target->value->type->data.enumeration.non_exhaustive) { |
| | 14224 | ir_add_error(ira, source_instr, |
| | 14225 | buf_sprintf("runtime cast to union '%s' from non-exhustive enum", |
| | 14226 | buf_ptr(&wanted_type->name))); |
| | 14227 | return ira->codegen->invalid_inst_gen; |
| | 14228 | } |
| | 14229 | |
| 14214 | // if the union has all fields 0 bits, we can do it | 14230 | // if the union has all fields 0 bits, we can do it |
| 14215 | // and in fact it's a noop cast because the union value is just the enum value | 14231 | // and in fact it's a noop cast because the union value is just the enum value |
| 14216 | if (wanted_type->data.unionation.gen_field_count == 0) { | 14232 | if (wanted_type->data.unionation.gen_field_count == 0) { |
| ... | @@ -23816,7 +23832,7 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -23816,7 +23832,7 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 23816 | bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); | 23832 | bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); |
| 23817 | return result; | 23833 | return result; |
| 23818 | } | 23834 | } |
| 23819 | if (tag_type->data.enumeration.src_field_count == 1) { | 23835 | if (tag_type->data.enumeration.src_field_count == 1 && !tag_type->data.enumeration.non_exhaustive) { |
| 23820 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); | 23836 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); |
| 23821 | TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; | 23837 | TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; |
| 23822 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); | 23838 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); |
| ... | @@ -23831,7 +23847,7 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, | ... | @@ -23831,7 +23847,7 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 23831 | case ZigTypeIdEnum: { | 23847 | case ZigTypeIdEnum: { |
| 23832 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) | 23848 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 23833 | return ira->codegen->invalid_inst_gen; | 23849 | return ira->codegen->invalid_inst_gen; |
| 23834 | if (target_type->data.enumeration.src_field_count == 1) { | 23850 | if (target_type->data.enumeration.src_field_count == 1 && !target_type->data.enumeration.non_exhaustive) { |
| 23835 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; | 23851 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 23836 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); | 23852 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); |
| 23837 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); | 23853 | bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value); |
| ... | @@ -28838,6 +28854,10 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -28838,6 +28854,10 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 28838 | if (type_is_invalid(switch_type)) | 28854 | if (type_is_invalid(switch_type)) |
| 28839 | return ira->codegen->invalid_inst_gen; | 28855 | return ira->codegen->invalid_inst_gen; |
| 28840 | | 28856 | |
| | 28857 | ZigValue *original_value = ((IrInstSrcSwitchTarget *)(instruction->target_value))->target_value_ptr->child->value; |
| | 28858 | bool target_is_originally_union = original_value->type->id == ZigTypeIdPointer && |
| | 28859 | original_value->type->data.pointer.child_type->id == ZigTypeIdUnion; |
| | 28860 | |
| 28841 | if (switch_type->id == ZigTypeIdEnum) { | 28861 | if (switch_type->id == ZigTypeIdEnum) { |
| 28842 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {}; | 28862 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {}; |
| 28843 | field_prev_uses.init(switch_type->data.enumeration.src_field_count); | 28863 | field_prev_uses.init(switch_type->data.enumeration.src_field_count); |
| ... | @@ -28893,9 +28913,12 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -28893,9 +28913,12 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 28893 | } | 28913 | } |
| 28894 | } | 28914 | } |
| 28895 | if (instruction->have_underscore_prong) { | 28915 | if (instruction->have_underscore_prong) { |
| 28896 | if (!switch_type->data.enumeration.non_exhaustive){ | 28916 | if (!switch_type->data.enumeration.non_exhaustive) { |
| | 28917 | ir_add_error(ira, &instruction->base.base, |
| | 28918 | buf_sprintf("switch on exhaustive enum has `_` prong")); |
| | 28919 | } else if (target_is_originally_union) { |
| 28897 | ir_add_error(ira, &instruction->base.base, | 28920 | ir_add_error(ira, &instruction->base.base, |
| 28898 | buf_sprintf("switch on non-exhaustive enum has `_` prong")); | 28921 | buf_sprintf("`_` prong not allowed when switching on tagged union")); |
| 28899 | } | 28922 | } |
| 28900 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { | 28923 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { |
| 28901 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; | 28924 | TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; |
| ... | @@ -28910,7 +28933,7 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, | ... | @@ -28910,7 +28933,7 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, |
| 28910 | } | 28933 | } |
| 28911 | } | 28934 | } |
| 28912 | } else if (instruction->else_prong == nullptr) { | 28935 | } else if (instruction->else_prong == nullptr) { |
| 28913 | if (switch_type->data.enumeration.non_exhaustive) { | 28936 | if (switch_type->data.enumeration.non_exhaustive && !target_is_originally_union) { |
| 28914 | ir_add_error(ira, &instruction->base.base, | 28937 | ir_add_error(ira, &instruction->base.base, |
| 28915 | buf_sprintf("switch on non-exhaustive enum must include `else` or `_` prong")); | 28938 | buf_sprintf("switch on non-exhaustive enum must include `else` or `_` prong")); |
| 28916 | } | 28939 | } |