diff options
| author | Vexu <git@vexu.eu> | 2020-07-27 18:04:08 +0300 |
|---|---|---|
| committer | Vexu <git@vexu.eu> | 2020-08-17 20:47:31 +0300 |
| commit | 1e835e0fccfd82deb31922ffdee821b0b418709f (patch) | |
| tree | 87e520b7517faba7ce3222c03dbf5496105f1304 /src/ir.cpp | |
| parent | 65185016f15ca69363113f85537542b0bdebe33f (diff) | |
| download | zig-1e835e0fccfd82deb31922ffdee821b0b418709f.tar.gz zig-1e835e0fccfd82deb31922ffdee821b0b418709f.zip | |
disallow '_' prong when switching on non-exhaustive tagged union
A tagged union cannot legally be initiated to an invalid enumeration
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index f56a0681df..347cae7e79 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -14138,7 +14138,7 @@ static IrInstGen *ir_analyze_union_to_tag(IrAnalyze *ira, IrInst* source_instr, // If there is only 1 possible tag, then we know at comptime what it is. if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && wanted_type->data.enumeration.src_field_count == 1 && - !wanted_type->data.enumeration.non_exhaustive) // TODO are non-exhaustive union tag types supposed to be allowed? + !wanted_type->data.enumeration.non_exhaustive) { IrInstGen *result = ir_const(ira, source_instr, wanted_type); result->value->special = ConstValSpecialStatic; @@ -23816,7 +23816,6 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira, bigint_init_bigint(&result->value->data.x_enum_tag, &pointee_val->data.x_union.tag); return result; } - // TODO are non-exhaustive union tag types supposed to be allowed? if (tag_type->data.enumeration.src_field_count == 1 && !tag_type->data.enumeration.non_exhaustive) { IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type); TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; @@ -28839,6 +28838,10 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, if (type_is_invalid(switch_type)) return ira->codegen->invalid_inst_gen; + ZigValue *original_value = ((IrInstSrcSwitchTarget *)(instruction->target_value))->target_value_ptr->child->value; + bool target_is_originally_union = original_value->type->id == ZigTypeIdPointer && + original_value->type->data.pointer.child_type->id == ZigTypeIdUnion; + if (switch_type->id == ZigTypeIdEnum) { HashMap<BigInt, AstNode *, bigint_hash, bigint_eql> field_prev_uses = {}; field_prev_uses.init(switch_type->data.enumeration.src_field_count); @@ -28894,9 +28897,12 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, } } if (instruction->have_underscore_prong) { - if (!switch_type->data.enumeration.non_exhaustive){ + if (!switch_type->data.enumeration.non_exhaustive) { + ir_add_error(ira, &instruction->base.base, + buf_sprintf("switch on exhaustive enum has `_` prong")); + } else if (target_is_originally_union) { ir_add_error(ira, &instruction->base.base, - buf_sprintf("switch on non-exhaustive enum has `_` prong")); + buf_sprintf("`_` prong not allowed when switching on tagged union")); } for (uint32_t i = 0; i < switch_type->data.enumeration.src_field_count; i += 1) { TypeEnumField *enum_field = &switch_type->data.enumeration.fields[i]; @@ -28911,7 +28917,7 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, } } } else if (instruction->else_prong == nullptr) { - if (switch_type->data.enumeration.non_exhaustive) { + if (switch_type->data.enumeration.non_exhaustive && !target_is_originally_union) { ir_add_error(ira, &instruction->base.base, buf_sprintf("switch on non-exhaustive enum must include `else` or `_` prong")); } |
