| author | |
| committer | |
| log | 4f7344dec0bc61916f0c9af99bc5b5e5b7167da3 |
| tree | 784154f34a6ec49d6245c6e6020db0afb2d237de |
| parent | ffc5242169d67840e0d1420b792696fc1b3d1722 |
| signature | Commit is signed but in an unrecognized format. |
Unions with no fields are now "uninstantiable" types, which work like
`noreturn` in that values of this type cannot exist. Enums with no
fields are different because they are currently considered `extern`
types, though https://github.com/ziglang/zig/issues/19855 will change
this in the future.7 files changed, 195 insertions(+), 67 deletions(-)
test/behavior.zig-1| ... | ... | @@ -24,7 +24,6 @@ test { |
| 24 | 24 | _ = @import("behavior/duplicated_test_names.zig"); |
| 25 | 25 | _ = @import("behavior/defer.zig"); |
| 26 | 26 | _ = @import("behavior/destructure.zig"); |
| 27 | _ = @import("behavior/empty_union.zig"); | |
| 28 | 27 | _ = @import("behavior/enum.zig"); |
| 29 | 28 | _ = @import("behavior/error.zig"); |
| 30 | 29 | _ = @import("behavior/eval.zig"); |
test/behavior/empty_union.zig deleted-66| ... | ... | @@ -1,66 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | const expect = std.testing.expect; | |
| 4 | ||
| 5 | test "switch on empty enum" { | |
| 6 | const E = enum {}; | |
| 7 | var e: E = undefined; | |
| 8 | _ = &e; | |
| 9 | switch (e) {} | |
| 10 | } | |
| 11 | ||
| 12 | test "switch on empty enum with a specified tag type" { | |
| 13 | const E = enum(u8) {}; | |
| 14 | var e: E = undefined; | |
| 15 | _ = &e; | |
| 16 | switch (e) {} | |
| 17 | } | |
| 18 | ||
| 19 | test "switch on empty auto numbered tagged union" { | |
| 20 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 21 | ||
| 22 | const U = union(enum(u8)) {}; | |
| 23 | var u: U = undefined; | |
| 24 | _ = &u; | |
| 25 | switch (u) {} | |
| 26 | } | |
| 27 | ||
| 28 | test "switch on empty tagged union" { | |
| 29 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 30 | ||
| 31 | const E = enum {}; | |
| 32 | const U = union(E) {}; | |
| 33 | var u: U = undefined; | |
| 34 | _ = &u; | |
| 35 | switch (u) {} | |
| 36 | } | |
| 37 | ||
| 38 | test "empty union" { | |
| 39 | const U = union {}; | |
| 40 | try expect(@sizeOf(U) == 0); | |
| 41 | try expect(@alignOf(U) == 1); | |
| 42 | } | |
| 43 | ||
| 44 | test "empty extern union" { | |
| 45 | const U = extern union {}; | |
| 46 | try expect(@sizeOf(U) == 0); | |
| 47 | try expect(@alignOf(U) == 1); | |
| 48 | } | |
| 49 | ||
| 50 | test "empty union passed as argument" { | |
| 51 | const U = union(enum) { | |
| 52 | fn f(u: @This()) void { | |
| 53 | switch (u) {} | |
| 54 | } | |
| 55 | }; | |
| 56 | U.f(@as(U, undefined)); | |
| 57 | } | |
| 58 | ||
| 59 | test "empty enum passed as argument" { | |
| 60 | const E = enum { | |
| 61 | fn f(e: @This()) void { | |
| 62 | switch (e) {} | |
| 63 | } | |
| 64 | }; | |
| 65 | E.f(@as(E, undefined)); | |
| 66 | } |
test/behavior/enum.zig+23| ... | ... | @@ -1331,3 +1331,26 @@ test "comptime @enumFromInt with signed arithmetic" { |
| 1331 | 1331 | comptime assert(x == .bar); |
| 1332 | 1332 | comptime assert(@intFromEnum(x) == 0); |
| 1333 | 1333 | } |
| 1334 | ||
| 1335 | test "switch on empty enum" { | |
| 1336 | const E = enum {}; | |
| 1337 | var e: E = undefined; | |
| 1338 | _ = &e; | |
| 1339 | switch (e) {} | |
| 1340 | } | |
| 1341 | ||
| 1342 | test "switch on empty enum with a specified tag type" { | |
| 1343 | const E = enum(u8) {}; | |
| 1344 | var e: E = undefined; | |
| 1345 | _ = &e; | |
| 1346 | switch (e) {} | |
| 1347 | } | |
| 1348 | ||
| 1349 | test "empty enum passed as argument" { | |
| 1350 | const E = enum { | |
| 1351 | fn f(e: @This()) void { | |
| 1352 | switch (e) {} | |
| 1353 | } | |
| 1354 | }; | |
| 1355 | E.f(@as(E, undefined)); | |
| 1356 | } |
test/cases/compile_errors/empty_extern_union.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | export fn foo() void { | |
| 2 | const U = extern union {}; | |
| 3 | _ = @as(U, undefined); | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // | |
| 8 | // :2:22: error: extern union has no fields |
test/cases/compile_errors/empty_packed_union.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | export fn foo() void { | |
| 2 | const U = packed union {}; | |
| 3 | _ = @as(U, undefined); | |
| 4 | } | |
| 5 | ||
| 6 | // error | |
| 7 | // | |
| 8 | // :2:22: error: packed union has no fields |
test/cases/compile_errors/initialize_empty_union.zig created+81| ... | ... | @@ -0,0 +1,81 @@ |
| 1 | const EnumInferred = enum {}; | |
| 2 | const EnumExplicit = enum(u8) {}; | |
| 3 | const EnumNonexhaustive = enum(u8) { _ }; | |
| 4 | ||
| 5 | const U0 = union {}; | |
| 6 | const U1 = union(enum) {}; | |
| 7 | const U2 = union(enum(u8)) {}; | |
| 8 | const U3 = union(EnumInferred) {}; | |
| 9 | const U4 = union(EnumExplicit) {}; | |
| 10 | const U5 = union(EnumNonexhaustive) {}; | |
| 11 | ||
| 12 | export fn init0() void { | |
| 13 | _ = @as(U0, undefined); | |
| 14 | } | |
| 15 | export fn init1() void { | |
| 16 | _ = @as(U1, undefined); | |
| 17 | } | |
| 18 | export fn init2() void { | |
| 19 | _ = @as(U2, undefined); | |
| 20 | } | |
| 21 | export fn init3() void { | |
| 22 | _ = @as(U3, undefined); | |
| 23 | } | |
| 24 | export fn init4() void { | |
| 25 | _ = @as(U4, undefined); | |
| 26 | } | |
| 27 | export fn init5() void { | |
| 28 | _ = @as(U5, undefined); | |
| 29 | } | |
| 30 | ||
| 31 | export fn deref0(ptr: *const U0) void { | |
| 32 | _ = ptr.*; | |
| 33 | } | |
| 34 | export fn deref1(ptr: *const U1) void { | |
| 35 | _ = ptr.*; | |
| 36 | } | |
| 37 | export fn deref2(ptr: *const U2) void { | |
| 38 | _ = ptr.*; | |
| 39 | } | |
| 40 | export fn deref3(ptr: *const U3) void { | |
| 41 | _ = ptr.*; | |
| 42 | } | |
| 43 | export fn deref4(ptr: *const U4) void { | |
| 44 | _ = ptr.*; | |
| 45 | } | |
| 46 | export fn deref5(ptr: *const U5) void { | |
| 47 | _ = ptr.*; | |
| 48 | } | |
| 49 | ||
| 50 | // error | |
| 51 | // | |
| 52 | // :13:17: error: expected type 'initialize_empty_union.U0', found '@TypeOf(undefined)' | |
| 53 | // :13:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U0' | |
| 54 | // :5:12: note: union declared here | |
| 55 | // :16:17: error: expected type 'initialize_empty_union.U1', found '@TypeOf(undefined)' | |
| 56 | // :16:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U1' | |
| 57 | // :6:12: note: union declared here | |
| 58 | // :19:17: error: expected type 'initialize_empty_union.U2', found '@TypeOf(undefined)' | |
| 59 | // :19:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U2' | |
| 60 | // :7:12: note: union declared here | |
| 61 | // :22:17: error: expected type 'initialize_empty_union.U3', found '@TypeOf(undefined)' | |
| 62 | // :22:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U3' | |
| 63 | // :8:12: note: union declared here | |
| 64 | // :25:17: error: expected type 'initialize_empty_union.U4', found '@TypeOf(undefined)' | |
| 65 | // :25:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U4' | |
| 66 | // :9:12: note: union declared here | |
| 67 | // :28:17: error: expected type 'initialize_empty_union.U5', found '@TypeOf(undefined)' | |
| 68 | // :28:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U5' | |
| 69 | // :10:12: note: union declared here | |
| 70 | // :32:12: error: cannot load uninstantiable type 'initialize_empty_union.U0' | |
| 71 | // :5:12: note: union declared here | |
| 72 | // :35:12: error: cannot load uninstantiable type 'initialize_empty_union.U1' | |
| 73 | // :6:12: note: union declared here | |
| 74 | // :38:12: error: cannot load uninstantiable type 'initialize_empty_union.U2' | |
| 75 | // :7:12: note: union declared here | |
| 76 | // :41:12: error: cannot load uninstantiable type 'initialize_empty_union.U3' | |
| 77 | // :8:12: note: union declared here | |
| 78 | // :44:12: error: cannot load uninstantiable type 'initialize_empty_union.U4' | |
| 79 | // :9:12: note: union declared here | |
| 80 | // :47:12: error: cannot load uninstantiable type 'initialize_empty_union.U5' | |
| 81 | // :10:12: note: union declared here |
test/cases/compile_errors/sizeof_alignof_empty_union.zig created+75| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | const EnumInferred = enum {}; | |
| 2 | const EnumExplicit = enum(u8) {}; | |
| 3 | const EnumNonexhaustive = enum(u8) { _ }; | |
| 4 | ||
| 5 | const U0 = union {}; | |
| 6 | const U1 = union(enum) {}; | |
| 7 | const U2 = union(enum(u8)) {}; | |
| 8 | const U3 = union(EnumInferred) {}; | |
| 9 | const U4 = union(EnumExplicit) {}; | |
| 10 | const U5 = union(EnumNonexhaustive) {}; | |
| 11 | ||
| 12 | export fn size0() void { | |
| 13 | _ = @sizeOf(U0); | |
| 14 | } | |
| 15 | export fn size1() void { | |
| 16 | _ = @sizeOf(U1); | |
| 17 | } | |
| 18 | export fn size2() void { | |
| 19 | _ = @sizeOf(U2); | |
| 20 | } | |
| 21 | export fn size3() void { | |
| 22 | _ = @sizeOf(U3); | |
| 23 | } | |
| 24 | export fn size4() void { | |
| 25 | _ = @sizeOf(U4); | |
| 26 | } | |
| 27 | export fn size5() void { | |
| 28 | _ = @sizeOf(U5); | |
| 29 | } | |
| 30 | ||
| 31 | export fn align0() void { | |
| 32 | _ = @alignOf(U0); | |
| 33 | } | |
| 34 | export fn align1() void { | |
| 35 | _ = @alignOf(U1); | |
| 36 | } | |
| 37 | export fn align2() void { | |
| 38 | _ = @alignOf(U2); | |
| 39 | } | |
| 40 | export fn align3() void { | |
| 41 | _ = @alignOf(U3); | |
| 42 | } | |
| 43 | export fn align4() void { | |
| 44 | _ = @alignOf(U4); | |
| 45 | } | |
| 46 | export fn align5() void { | |
| 47 | _ = @alignOf(U5); | |
| 48 | } | |
| 49 | ||
| 50 | // error | |
| 51 | // | |
| 52 | // :13:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U0' | |
| 53 | // :5:12: note: union declared here | |
| 54 | // :16:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U1' | |
| 55 | // :6:12: note: union declared here | |
| 56 | // :19:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U2' | |
| 57 | // :7:12: note: union declared here | |
| 58 | // :22:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U3' | |
| 59 | // :8:12: note: union declared here | |
| 60 | // :25:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U4' | |
| 61 | // :9:12: note: union declared here | |
| 62 | // :28:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U5' | |
| 63 | // :10:12: note: union declared here | |
| 64 | // :32:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U0' | |
| 65 | // :5:12: note: union declared here | |
| 66 | // :35:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U1' | |
| 67 | // :6:12: note: union declared here | |
| 68 | // :38:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U2' | |
| 69 | // :7:12: note: union declared here | |
| 70 | // :41:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U3' | |
| 71 | // :8:12: note: union declared here | |
| 72 | // :44:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U4' | |
| 73 | // :9:12: note: union declared here | |
| 74 | // :47:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U5' | |
| 75 | // :10:12: note: union declared here |