mirror of
https://github.com/ziglang/zig.git
synced 2026-01-09 08:55:36 +00:00
stage1: Don't fold single-element enums too aggressively
When the tag type is not a zero-sized type (eg. `enum(i32)`) we absolutely need to avoid constant-folding this values. Doing so masked any invalid input and, since the folding was not even applied consistently, introduced some hard to catch errors.
This commit is contained in:
parent
0f7954831a
commit
97f36d93f4
@ -14186,6 +14186,18 @@ static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, AstNode *source_node,
|
||||
}
|
||||
}
|
||||
|
||||
static bool can_fold_enum_type(ZigType *ty) {
|
||||
assert(ty->id == ZigTypeIdEnum);
|
||||
// We can fold the enum type (and avoid any check, be it at runtime or at
|
||||
// compile time) iff it has only a single element and its tag type is
|
||||
// zero-sized.
|
||||
ZigType *tag_int_type = ty->data.enumeration.tag_int_type;
|
||||
return ty->data.enumeration.layout == ContainerLayoutAuto &&
|
||||
ty->data.enumeration.src_field_count == 1 &&
|
||||
!ty->data.enumeration.non_exhaustive &&
|
||||
(tag_int_type->id == ZigTypeIdInt && tag_int_type->data.integral.bit_count == 0);
|
||||
}
|
||||
|
||||
static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, IrInstGen *target) {
|
||||
Error err;
|
||||
|
||||
@ -14214,10 +14226,7 @@ static IrInstGen *ir_analyze_enum_to_int(IrAnalyze *ira, IrInst *source_instr, I
|
||||
assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt);
|
||||
|
||||
// If there is only one possible tag, then we know at comptime what it is.
|
||||
if (enum_type->data.enumeration.layout == ContainerLayoutAuto &&
|
||||
enum_type->data.enumeration.src_field_count == 1 &&
|
||||
!enum_type->data.enumeration.non_exhaustive)
|
||||
{
|
||||
if (can_fold_enum_type(enum_type)) {
|
||||
IrInstGen *result = ir_const(ira, source_instr, tag_type);
|
||||
init_const_bigint(result->value, tag_type,
|
||||
&enum_type->data.enumeration.fields[0].value);
|
||||
@ -14255,10 +14264,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)
|
||||
{
|
||||
if (can_fold_enum_type(wanted_type)) {
|
||||
IrInstGen *result = ir_const(ira, source_instr, wanted_type);
|
||||
result->value->special = ConstValSpecialStatic;
|
||||
result->value->type = wanted_type;
|
||||
@ -24039,7 +24045,8 @@ 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;
|
||||
}
|
||||
if (tag_type->data.enumeration.src_field_count == 1 && !tag_type->data.enumeration.non_exhaustive) {
|
||||
|
||||
if (can_fold_enum_type(tag_type)) {
|
||||
IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, tag_type);
|
||||
TypeEnumField *only_field = &tag_type->data.enumeration.fields[0];
|
||||
bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
|
||||
@ -24054,7 +24061,8 @@ static IrInstGen *ir_analyze_instruction_switch_target(IrAnalyze *ira,
|
||||
case ZigTypeIdEnum: {
|
||||
if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
if (target_type->data.enumeration.src_field_count == 1 && !target_type->data.enumeration.non_exhaustive) {
|
||||
|
||||
if (can_fold_enum_type(target_type)) {
|
||||
TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
|
||||
IrInstGen *result = ir_const(ira, &switch_target_instruction->base.base, target_type);
|
||||
bigint_init_bigint(&result->value->data.x_enum_tag, &only_field->value);
|
||||
@ -24789,7 +24797,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc
|
||||
if (type_is_invalid(target->value->type))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
|
||||
if (target->value->type->id == ZigTypeIdEnumLiteral) {
|
||||
ZigType *target_type = target->value->type;
|
||||
|
||||
if (target_type->id == ZigTypeIdEnumLiteral) {
|
||||
IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);
|
||||
Buf *field_name = target->value->data.x_enum_literal;
|
||||
ZigValue *array_val = create_const_str_lit(ira->codegen, field_name)->data.x_ptr.data.ref.pointee;
|
||||
@ -24797,21 +24807,21 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc
|
||||
return result;
|
||||
}
|
||||
|
||||
if (target->value->type->id == ZigTypeIdUnion) {
|
||||
if (target_type->id == ZigTypeIdUnion) {
|
||||
target = ir_analyze_union_tag(ira, &instruction->base.base, target, instruction->base.is_gen);
|
||||
if (type_is_invalid(target->value->type))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
target_type = target->value->type;
|
||||
}
|
||||
|
||||
if (target->value->type->id != ZigTypeIdEnum) {
|
||||
if (target_type->id != ZigTypeIdEnum) {
|
||||
ir_add_error(ira, &target->base,
|
||||
buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target->value->type->name)));
|
||||
buf_sprintf("expected enum tag, found '%s'", buf_ptr(&target_type->name)));
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
}
|
||||
|
||||
if (target->value->type->data.enumeration.src_field_count == 1 &&
|
||||
!target->value->type->data.enumeration.non_exhaustive) {
|
||||
TypeEnumField *only_field = &target->value->type->data.enumeration.fields[0];
|
||||
if (can_fold_enum_type(target_type)) {
|
||||
TypeEnumField *only_field = &target_type->data.enumeration.fields[0];
|
||||
ZigValue *array_val = create_const_str_lit(ira->codegen, only_field->name)->data.x_ptr.data.ref.pointee;
|
||||
IrInstGen *result = ir_const(ira, &instruction->base.base, nullptr);
|
||||
init_const_slice(ira->codegen, result->value, array_val, 0, buf_len(only_field->name), true);
|
||||
@ -24819,9 +24829,9 @@ static IrInstGen *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrInstSrc
|
||||
}
|
||||
|
||||
if (instr_is_comptime(target)) {
|
||||
if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusZeroBitsKnown)))
|
||||
if ((err = type_resolve(ira->codegen, target_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_inst_gen;
|
||||
TypeEnumField *field = find_enum_field_by_tag(target->value->type, &target->value->data.x_bigint);
|
||||
TypeEnumField *field = find_enum_field_by_tag(target_type, &target->value->data.x_bigint);
|
||||
if (field == nullptr) {
|
||||
Buf *int_buf = buf_alloc();
|
||||
bigint_append_buf(int_buf, &target->value->data.x_bigint, 10);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user