commit 4f7344dec0bc61916f0c9af99bc5b5e5b7167da3 (tree)
parent ffc5242169d67840e0d1420b792696fc1b3d1722
Author: Matthew Lugg <mlugg@mlugg.co.uk>
Date: Sun, 8 Feb 2026 14:11:09 +0000
tests: update for accepted language change
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.
Diffstat:
7 files changed, 195 insertions(+), 67 deletions(-)
diff --git a/test/behavior.zig b/test/behavior.zig
@@ -24,7 +24,6 @@ test {
_ = @import("behavior/duplicated_test_names.zig");
_ = @import("behavior/defer.zig");
_ = @import("behavior/destructure.zig");
- _ = @import("behavior/empty_union.zig");
_ = @import("behavior/enum.zig");
_ = @import("behavior/error.zig");
_ = @import("behavior/eval.zig");
diff --git a/test/behavior/empty_union.zig b/test/behavior/empty_union.zig
@@ -1,66 +0,0 @@
-const builtin = @import("builtin");
-const std = @import("std");
-const expect = std.testing.expect;
-
-test "switch on empty enum" {
- const E = enum {};
- var e: E = undefined;
- _ = &e;
- switch (e) {}
-}
-
-test "switch on empty enum with a specified tag type" {
- const E = enum(u8) {};
- var e: E = undefined;
- _ = &e;
- switch (e) {}
-}
-
-test "switch on empty auto numbered tagged union" {
- if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
-
- const U = union(enum(u8)) {};
- var u: U = undefined;
- _ = &u;
- switch (u) {}
-}
-
-test "switch on empty tagged union" {
- if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
-
- const E = enum {};
- const U = union(E) {};
- var u: U = undefined;
- _ = &u;
- switch (u) {}
-}
-
-test "empty union" {
- const U = union {};
- try expect(@sizeOf(U) == 0);
- try expect(@alignOf(U) == 1);
-}
-
-test "empty extern union" {
- const U = extern union {};
- try expect(@sizeOf(U) == 0);
- try expect(@alignOf(U) == 1);
-}
-
-test "empty union passed as argument" {
- const U = union(enum) {
- fn f(u: @This()) void {
- switch (u) {}
- }
- };
- U.f(@as(U, undefined));
-}
-
-test "empty enum passed as argument" {
- const E = enum {
- fn f(e: @This()) void {
- switch (e) {}
- }
- };
- E.f(@as(E, undefined));
-}
diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig
@@ -1331,3 +1331,26 @@ test "comptime @enumFromInt with signed arithmetic" {
comptime assert(x == .bar);
comptime assert(@intFromEnum(x) == 0);
}
+
+test "switch on empty enum" {
+ const E = enum {};
+ var e: E = undefined;
+ _ = &e;
+ switch (e) {}
+}
+
+test "switch on empty enum with a specified tag type" {
+ const E = enum(u8) {};
+ var e: E = undefined;
+ _ = &e;
+ switch (e) {}
+}
+
+test "empty enum passed as argument" {
+ const E = enum {
+ fn f(e: @This()) void {
+ switch (e) {}
+ }
+ };
+ E.f(@as(E, undefined));
+}
diff --git a/test/cases/compile_errors/empty_extern_union.zig b/test/cases/compile_errors/empty_extern_union.zig
@@ -0,0 +1,8 @@
+export fn foo() void {
+ const U = extern union {};
+ _ = @as(U, undefined);
+}
+
+// error
+//
+// :2:22: error: extern union has no fields
diff --git a/test/cases/compile_errors/empty_packed_union.zig b/test/cases/compile_errors/empty_packed_union.zig
@@ -0,0 +1,8 @@
+export fn foo() void {
+ const U = packed union {};
+ _ = @as(U, undefined);
+}
+
+// error
+//
+// :2:22: error: packed union has no fields
diff --git a/test/cases/compile_errors/initialize_empty_union.zig b/test/cases/compile_errors/initialize_empty_union.zig
@@ -0,0 +1,81 @@
+const EnumInferred = enum {};
+const EnumExplicit = enum(u8) {};
+const EnumNonexhaustive = enum(u8) { _ };
+
+const U0 = union {};
+const U1 = union(enum) {};
+const U2 = union(enum(u8)) {};
+const U3 = union(EnumInferred) {};
+const U4 = union(EnumExplicit) {};
+const U5 = union(EnumNonexhaustive) {};
+
+export fn init0() void {
+ _ = @as(U0, undefined);
+}
+export fn init1() void {
+ _ = @as(U1, undefined);
+}
+export fn init2() void {
+ _ = @as(U2, undefined);
+}
+export fn init3() void {
+ _ = @as(U3, undefined);
+}
+export fn init4() void {
+ _ = @as(U4, undefined);
+}
+export fn init5() void {
+ _ = @as(U5, undefined);
+}
+
+export fn deref0(ptr: *const U0) void {
+ _ = ptr.*;
+}
+export fn deref1(ptr: *const U1) void {
+ _ = ptr.*;
+}
+export fn deref2(ptr: *const U2) void {
+ _ = ptr.*;
+}
+export fn deref3(ptr: *const U3) void {
+ _ = ptr.*;
+}
+export fn deref4(ptr: *const U4) void {
+ _ = ptr.*;
+}
+export fn deref5(ptr: *const U5) void {
+ _ = ptr.*;
+}
+
+// error
+//
+// :13:17: error: expected type 'initialize_empty_union.U0', found '@TypeOf(undefined)'
+// :13:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U0'
+// :5:12: note: union declared here
+// :16:17: error: expected type 'initialize_empty_union.U1', found '@TypeOf(undefined)'
+// :16:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U1'
+// :6:12: note: union declared here
+// :19:17: error: expected type 'initialize_empty_union.U2', found '@TypeOf(undefined)'
+// :19:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U2'
+// :7:12: note: union declared here
+// :22:17: error: expected type 'initialize_empty_union.U3', found '@TypeOf(undefined)'
+// :22:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U3'
+// :8:12: note: union declared here
+// :25:17: error: expected type 'initialize_empty_union.U4', found '@TypeOf(undefined)'
+// :25:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U4'
+// :9:12: note: union declared here
+// :28:17: error: expected type 'initialize_empty_union.U5', found '@TypeOf(undefined)'
+// :28:17: note: cannot coerce to uninstantiable type 'initialize_empty_union.U5'
+// :10:12: note: union declared here
+// :32:12: error: cannot load uninstantiable type 'initialize_empty_union.U0'
+// :5:12: note: union declared here
+// :35:12: error: cannot load uninstantiable type 'initialize_empty_union.U1'
+// :6:12: note: union declared here
+// :38:12: error: cannot load uninstantiable type 'initialize_empty_union.U2'
+// :7:12: note: union declared here
+// :41:12: error: cannot load uninstantiable type 'initialize_empty_union.U3'
+// :8:12: note: union declared here
+// :44:12: error: cannot load uninstantiable type 'initialize_empty_union.U4'
+// :9:12: note: union declared here
+// :47:12: error: cannot load uninstantiable type 'initialize_empty_union.U5'
+// :10:12: note: union declared here
diff --git a/test/cases/compile_errors/sizeof_alignof_empty_union.zig b/test/cases/compile_errors/sizeof_alignof_empty_union.zig
@@ -0,0 +1,75 @@
+const EnumInferred = enum {};
+const EnumExplicit = enum(u8) {};
+const EnumNonexhaustive = enum(u8) { _ };
+
+const U0 = union {};
+const U1 = union(enum) {};
+const U2 = union(enum(u8)) {};
+const U3 = union(EnumInferred) {};
+const U4 = union(EnumExplicit) {};
+const U5 = union(EnumNonexhaustive) {};
+
+export fn size0() void {
+ _ = @sizeOf(U0);
+}
+export fn size1() void {
+ _ = @sizeOf(U1);
+}
+export fn size2() void {
+ _ = @sizeOf(U2);
+}
+export fn size3() void {
+ _ = @sizeOf(U3);
+}
+export fn size4() void {
+ _ = @sizeOf(U4);
+}
+export fn size5() void {
+ _ = @sizeOf(U5);
+}
+
+export fn align0() void {
+ _ = @alignOf(U0);
+}
+export fn align1() void {
+ _ = @alignOf(U1);
+}
+export fn align2() void {
+ _ = @alignOf(U2);
+}
+export fn align3() void {
+ _ = @alignOf(U3);
+}
+export fn align4() void {
+ _ = @alignOf(U4);
+}
+export fn align5() void {
+ _ = @alignOf(U5);
+}
+
+// error
+//
+// :13:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U0'
+// :5:12: note: union declared here
+// :16:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U1'
+// :6:12: note: union declared here
+// :19:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U2'
+// :7:12: note: union declared here
+// :22:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U3'
+// :8:12: note: union declared here
+// :25:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U4'
+// :9:12: note: union declared here
+// :28:17: error: no size available for uninstantiable type 'sizeof_alignof_empty_union.U5'
+// :10:12: note: union declared here
+// :32:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U0'
+// :5:12: note: union declared here
+// :35:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U1'
+// :6:12: note: union declared here
+// :38:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U2'
+// :7:12: note: union declared here
+// :41:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U3'
+// :8:12: note: union declared here
+// :44:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U4'
+// :9:12: note: union declared here
+// :47:18: error: no align available for uninstantiable type 'sizeof_alignof_empty_union.U5'
+// :10:12: note: union declared here