@@ -7468,6 +7468,17 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
7468
7468
}
7469
7469
}
7470
7470
7471
+ // implicit enum to union which has the enum as the tag type
7472
+ if (expected_type->id == TypeTableEntryIdUnion && actual_type->id == TypeTableEntryIdEnum &&
7473
+ (expected_type->data.unionation.decl_node->data.container_decl.auto_enum ||
7474
+ expected_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
7475
+ {
7476
+ type_ensure_zero_bits_known(ira->codegen, expected_type);
7477
+ if (expected_type->data.unionation.tag_type == actual_type) {
7478
+ return ImplicitCastMatchResultYes;
7479
+ }
7480
+ }
7481
+
7471
7482
// implicit undefined literal to anything
7472
7483
if (actual_type->id == TypeTableEntryIdUndefLit) {
7473
7484
return ImplicitCastMatchResultYes;
@@ -8370,6 +8381,63 @@ static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruc
8370
8381
return result;
8371
8382
}
8372
8383
8384
+ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *source_instr,
8385
+ IrInstruction *target, TypeTableEntry *wanted_type)
8386
+ {
8387
+ assert(wanted_type->id == TypeTableEntryIdUnion);
8388
+ assert(target->value.type->id == TypeTableEntryIdEnum);
8389
+
8390
+ if (instr_is_comptime(target)) {
8391
+ ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
8392
+ if (!val)
8393
+ return ira->codegen->invalid_instruction;
8394
+ TypeUnionField *union_field = find_union_field_by_tag(wanted_type, &val->data.x_enum_tag);
8395
+ assert(union_field != nullptr);
8396
+ type_ensure_zero_bits_known(ira->codegen, union_field->type_entry);
8397
+ if (!union_field->type_entry->zero_bits) {
8398
+ AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(
8399
+ union_field->enum_field->decl_index);
8400
+ ErrorMsg *msg = ir_add_error(ira, source_instr,
8401
+ buf_sprintf("cast to union '%s' must initialize '%s' field '%s'",
8402
+ buf_ptr(&wanted_type->name),
8403
+ buf_ptr(&union_field->type_entry->name),
8404
+ buf_ptr(union_field->name)));
8405
+ add_error_note(ira->codegen, msg, field_node,
8406
+ buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
8407
+ return ira->codegen->invalid_instruction;
8408
+ }
8409
+ IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
8410
+ source_instr->source_node, wanted_type);
8411
+ result->value.special = ConstValSpecialStatic;
8412
+ result->value.type = wanted_type;
8413
+ bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);
8414
+ return result;
8415
+ }
8416
+
8417
+ // if the union has all fields 0 bits, we can do it
8418
+ // and in fact it's a noop cast because the union value is just the enum value
8419
+ if (wanted_type->data.unionation.gen_field_count == 0) {
8420
+ IrInstruction *result = ir_build_cast(&ira->new_irb, target->scope, target->source_node, wanted_type, target, CastOpNoop);
8421
+ result->value.type = wanted_type;
8422
+ return result;
8423
+ }
8424
+
8425
+ ErrorMsg *msg = ir_add_error(ira, source_instr,
8426
+ buf_sprintf("runtime cast to union '%s' which has non-void fields",
8427
+ buf_ptr(&wanted_type->name)));
8428
+ for (uint32_t i = 0; i < wanted_type->data.unionation.src_field_count; i += 1) {
8429
+ TypeUnionField *union_field = &wanted_type->data.unionation.fields[i];
8430
+ if (type_has_bits(union_field->type_entry)) {
8431
+ AstNode *field_node = wanted_type->data.unionation.decl_node->data.container_decl.fields.at(i);
8432
+ add_error_note(ira->codegen, msg, field_node,
8433
+ buf_sprintf("field '%s' has type '%s'",
8434
+ buf_ptr(union_field->name),
8435
+ buf_ptr(&union_field->type_entry->name)));
8436
+ }
8437
+ }
8438
+ return ira->codegen->invalid_instruction;
8439
+ }
8440
+
8373
8441
static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction *source_instr,
8374
8442
IrInstruction *target, TypeTableEntry *wanted_type)
8375
8443
{
@@ -8919,6 +8987,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
8919
8987
}
8920
8988
}
8921
8989
8990
+ // explicit enum to union which has the enum as the tag type
8991
+ if (wanted_type->id == TypeTableEntryIdUnion && actual_type->id == TypeTableEntryIdEnum &&
8992
+ (wanted_type->data.unionation.decl_node->data.container_decl.auto_enum ||
8993
+ wanted_type->data.unionation.decl_node->data.container_decl.init_arg_expr != nullptr))
8994
+ {
8995
+ type_ensure_zero_bits_known(ira->codegen, wanted_type);
8996
+ if (wanted_type->data.unionation.tag_type == actual_type) {
8997
+ return ir_analyze_enum_to_union(ira, source_instr, value, wanted_type);
8998
+ }
8999
+ }
9000
+
8922
9001
// explicit cast from undefined to anything
8923
9002
if (actual_type->id == TypeTableEntryIdUndefLit) {
8924
9003
return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
0 commit comments