| author | |
| committer | |
| log | 51b1083d66b29d110c8cf60b59052170dd34a95f |
| tree | 4d2d18a6358c4a3ce3a2957d101dbc793b3d37d3 |
| parent | 42db468dcb3de15426f9f8ec8da78e36155e3510 |
Closes #134023 files changed, 42 insertions(+), 20 deletions(-)
src/Sema.zig+13-10| ... | ... | @@ -10343,6 +10343,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10343 | 10343 | } |
| 10344 | 10344 | if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand); |
| 10345 | 10345 | if (special.is_inline) child_block.inline_case_capture = operand; |
| 10346 | if (empty_enum) { | |
| 10347 | return Air.Inst.Ref.void_value; | |
| 10348 | } | |
| 10346 | 10349 | return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges); |
| 10347 | 10350 | } |
| 10348 | 10351 | |
| ... | ... | @@ -30479,23 +30482,23 @@ pub fn typeHasOnePossibleValue( |
| 30479 | 30482 | if (enum_obj.tag_ty.hasRuntimeBits()) { |
| 30480 | 30483 | return null; |
| 30481 | 30484 | } |
| 30482 | if (enum_obj.fields.count() == 1) { | |
| 30483 | if (enum_obj.values.count() == 0) { | |
| 30485 | switch (enum_obj.fields.count()) { | |
| 30486 | 0 => return Value.initTag(.unreachable_value), | |
| 30487 | 1 => if (enum_obj.values.count() == 0) { | |
| 30484 | 30488 | return Value.zero; // auto-numbered |
| 30485 | 30489 | } else { |
| 30486 | 30490 | return enum_obj.values.keys()[0]; |
| 30487 | } | |
| 30488 | } else { | |
| 30489 | return null; | |
| 30491 | }, | |
| 30492 | else => return null, | |
| 30490 | 30493 | } |
| 30491 | 30494 | }, |
| 30492 | 30495 | .enum_simple => { |
| 30493 | 30496 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 30494 | 30497 | const enum_simple = resolved_ty.castTag(.enum_simple).?.data; |
| 30495 | if (enum_simple.fields.count() == 1) { | |
| 30496 | return Value.zero; | |
| 30497 | } else { | |
| 30498 | return null; | |
| 30498 | switch (enum_simple.fields.count()) { | |
| 30499 | 0 => return Value.initTag(.unreachable_value), | |
| 30500 | 1 => return Value.zero, | |
| 30501 | else => return null, | |
| 30499 | 30502 | } |
| 30500 | 30503 | }, |
| 30501 | 30504 | .enum_nonexhaustive => { |
| ... | ... | @@ -30512,7 +30515,7 @@ pub fn typeHasOnePossibleValue( |
| 30512 | 30515 | const tag_val = (try sema.typeHasOnePossibleValue(block, src, union_obj.tag_ty)) orelse |
| 30513 | 30516 | return null; |
| 30514 | 30517 | const fields = union_obj.fields.values(); |
| 30515 | if (fields.len == 0) return Value.initTag(.empty_struct_value); | |
| 30518 | if (fields.len == 0) return Value.initTag(.unreachable_value); | |
| 30516 | 30519 | const only_field = fields[0]; |
| 30517 | 30520 | if (only_field.ty.eql(resolved_ty, sema.mod)) { |
| 30518 | 30521 | const msg = try Module.ErrorMsg.create( |
src/type.zig+11-10| ... | ... | @@ -5015,22 +5015,22 @@ pub const Type = extern union { |
| 5015 | 5015 | if (enum_full.tag_ty.hasRuntimeBits()) { |
| 5016 | 5016 | return null; |
| 5017 | 5017 | } |
| 5018 | if (enum_full.fields.count() == 1) { | |
| 5019 | if (enum_full.values.count() == 0) { | |
| 5020 | return Value.zero; | |
| 5018 | switch (enum_full.fields.count()) { | |
| 5019 | 0 => return Value.initTag(.unreachable_value), | |
| 5020 | 1 => if (enum_full.values.count() == 0) { | |
| 5021 | return Value.zero; // auto-numbered | |
| 5021 | 5022 | } else { |
| 5022 | 5023 | return enum_full.values.keys()[0]; |
| 5023 | } | |
| 5024 | } else { | |
| 5025 | return null; | |
| 5024 | }, | |
| 5025 | else => return null, | |
| 5026 | 5026 | } |
| 5027 | 5027 | }, |
| 5028 | 5028 | .enum_simple => { |
| 5029 | 5029 | const enum_simple = ty.castTag(.enum_simple).?.data; |
| 5030 | if (enum_simple.fields.count() == 1) { | |
| 5031 | return Value.zero; | |
| 5032 | } else { | |
| 5033 | return null; | |
| 5030 | switch (enum_simple.fields.count()) { | |
| 5031 | 0 => return Value.initTag(.unreachable_value), | |
| 5032 | 1 => return Value.zero, | |
| 5033 | else => return null, | |
| 5034 | 5034 | } |
| 5035 | 5035 | }, |
| 5036 | 5036 | .enum_nonexhaustive => { |
| ... | ... | @@ -5044,6 +5044,7 @@ pub const Type = extern union { |
| 5044 | 5044 | .@"union", .union_safety_tagged, .union_tagged => { |
| 5045 | 5045 | const union_obj = ty.cast(Payload.Union).?.data; |
| 5046 | 5046 | const tag_val = union_obj.tag_ty.onePossibleValue() orelse return null; |
| 5047 | if (union_obj.fields.count() == 0) return Value.initTag(.unreachable_value); | |
| 5047 | 5048 | const only_field = union_obj.fields.values()[0]; |
| 5048 | 5049 | const val_val = only_field.ty.onePossibleValue() orelse return null; |
| 5049 | 5050 | _ = tag_val; |
test/behavior/empty_union.zig+18| ... | ... | @@ -48,3 +48,21 @@ test "empty extern union" { |
| 48 | 48 | try expect(@sizeOf(U) == 0); |
| 49 | 49 | try expect(@alignOf(U) == 1); |
| 50 | 50 | } |
| 51 | ||
| 52 | test "empty union passed as argument" { | |
| 53 | const U = union(enum) { | |
| 54 | fn f(u: @This()) void { | |
| 55 | switch (u) {} | |
| 56 | } | |
| 57 | }; | |
| 58 | U.f(@as(U, undefined)); | |
| 59 | } | |
| 60 | ||
| 61 | test "empty enum passed as argument" { | |
| 62 | const E = enum { | |
| 63 | fn f(e: @This()) void { | |
| 64 | switch (e) {} | |
| 65 | } | |
| 66 | }; | |
| 67 | E.f(@as(E, undefined)); | |
| 68 | } |