| ... | ... | @@ -14096,7 +14096,8 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I |
| 14096 | 14096 | |
| 14097 | 14097 | // If there is only one possible tag, then we know at comptime what it is. |
| 14098 | 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 | 14102 | IrInstGen *result = ir_const(ira, source_instr, tag_type); |
| 14102 | 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 | 14137 | |
| 14137 | 14138 | // If there is only 1 possible tag, then we know at comptime what it is. |
| 14138 | 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 | 14143 | IrInstGen *result = ir_const(ira, source_instr, wanted_type); |
| 14142 | 14144 | result->value->special = ConstValSpecialStatic; |
| ... | ... | @@ -14175,7 +14177,14 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, |
| 14175 | 14177 | if (!val) |
| 14176 | 14178 | return ira->codegen->invalid_inst_gen; |
| 14177 | 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 | 14188 | ZigType *field_type = resolve_union_field_type(ira->codegen, union_field); |
| 14180 | 14189 | if (field_type == nullptr) |
| 14181 | 14190 | return ira->codegen->invalid_inst_gen; |
| ... | ... | @@ -14211,6 +14220,13 @@ static IrInstGen *ir_analyze_enum_to_union(IrAnalyze *ira, IrInst* source_instr, |
| 14211 | 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 | 14230 | // if the union has all fields 0 bits, we can do it |
| 14215 | 14231 | // and in fact it's a noop cast because the union value is just the enum value |
| 14216 | 14232 | if (wanted_type->data.unionation.gen_field_count == 0) { |
| ... | ... | @@ -23816,7 +23832,7 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 23816 | 23832 | bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); |
| 23817 | 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 | 23836 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); |
| 23821 | 23837 | TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; |
| 23822 | 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 | 23847 | case ZigTypeIdEnum: { |
| 23832 | 23848 | if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown))) |
| 23833 | 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 | 23851 | TypeEnumField *only_field = &target_type->data.enumeration.fields[0]; |
| 23836 | 23852 | IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type); |
| 23837 | 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 | 28854 | if (type_is_invalid(switch_type)) |
| 28839 | 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 | 28861 | if (switch_type->id == ZigTypeIdEnum) { |
| 28842 | 28862 | HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {}; |
| 28843 | 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 | 28913 | } |
| 28894 | 28914 | } |
| 28895 | 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 | 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 | 28923 | for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { |
| 28901 | 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 | 28933 | } |
| 28911 | 28934 | } |
| 28912 | 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 | 28937 | ir_add_error(ira, &instruction->base.base, |
| 28915 | 28938 | buf_sprintf("switch on non-exhaustive enum must include `else` or `_` prong")); |
| 28916 | 28939 | } |