From f9183edf08214d3ff014cfe26a5f218385ef5ccc Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Sun, 8 Feb 2026 14:40:18 +0000 Subject: [PATCH] tests: update for accepted language change `packed struct`s and `packed union`s can no longer contain pointer fields. There are a few reasons for this, but in particular, binary formats do not typically support the relocation types we would need to lower such values into static memory. See the proposal at https://github.com/ziglang/zig/issues/24657 for details. --- test/behavior/bitcast.zig | 29 ------ test/behavior/packed-struct.zig | 98 ------------------- test/behavior/packed-union.zig | 12 --- test/behavior/union.zig | 30 +----- ...truct_with_fields_of_not_allowed_types.zig | 8 ++ ...cked_union_with_automatic_layout_field.zig | 18 ---- ...union_with_fields_of_not_allowed_types.zig | 20 ++++ 7 files changed, 33 insertions(+), 182 deletions(-) delete mode 100644 test/cases/compile_errors/packed_union_with_automatic_layout_field.zig create mode 100644 test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index 90cf8a5c77..90d185c63f 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -511,35 +511,6 @@ test "@bitCast of packed struct of bools all false" { try expect(@as(u8, @as(u4, @bitCast(p))) == 0); } -test "@bitCast of packed struct containing pointer" { - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179 - - const S = struct { - const A = packed struct { - ptr: *const u32, - }; - - const B = packed struct { - ptr: *const i32, - }; - - fn doTheTest() !void { - const x: u32 = 123; - var a: A = undefined; - a = .{ .ptr = &x }; - const b: B = @bitCast(a); - try expect(b.ptr.* == 123); - } - }; - - try S.doTheTest(); - try comptime S.doTheTest(); -} - test "@bitCast of extern struct containing pointer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 72e97bef95..1b019acb72 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -438,27 +438,6 @@ test "nested packed struct field pointers" { try expectEqual(6, ptr_p1_b.*); } -test "load pointer from packed struct" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - - const A = struct { - index: u16, - }; - const B = packed struct { - x: *A, - y: u32, - }; - var a: A = .{ .index = 123 }; - const b_list: []const B = &.{.{ .x = &a, .y = 99 }}; - for (b_list) |b| { - try expect(b.x.index == 123); - } -} - test "@intFromPtr on a packed struct field" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -601,19 +580,6 @@ test "packed struct fields modification" { try expect(@as(u16, @bitCast(Small.p)) == 0x1313); } -test "optional pointer in packed struct" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - - const T = packed struct { ptr: ?*const u8 }; - var n: u8 = 0; - const x = T{ .ptr = &n }; - try expect(x.ptr.? == &n); -} - test "nested packed struct field access test" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO packed structs larger than 64 bits @@ -1042,48 +1008,6 @@ test "packed struct acts as a namespace" { try expect(foo == .fizz); } -test "pointer loaded correctly from packed struct" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - - if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // crashes MSVC - - const RAM = struct { - data: [0xFFFF + 1]u8, - fn new() !@This() { - return .{ .data = [_]u8{0} ** 0x10000 }; - } - fn get(self: *@This(), addr: u16) u8 { - return self.data[addr]; - } - }; - - const CPU = packed struct { - interrupts: bool, - ram: *RAM, - fn new(ram: *RAM) !@This() { - return .{ - .ram = ram, - .interrupts = false, - }; - } - fn tick(self: *@This()) !void { - const queued_interrupts = self.ram.get(0xFFFF) & self.ram.get(0xFF0F); - if (self.interrupts and queued_interrupts != 0) { - self.interrupts = false; - } - } - }; - - var ram = try RAM.new(); - var cpu = try CPU.new(&ram); - try cpu.tick(); - try std.testing.expect(cpu.interrupts == false); -} - test "assignment to non-byte-aligned field in packed struct" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -1227,13 +1151,6 @@ test "2-byte packed struct argument in C calling convention" { } } -test "packed struct contains optional pointer" { - const foo: packed struct { - a: ?*@This() = null, - } = .{}; - try expect(foo.a == null); -} - test "packed struct equality" { const Foo = packed struct { a: u4, @@ -1297,21 +1214,6 @@ test "assign packed struct initialized with RLS to packed struct literal field" try expect(outer.x == x); } -test "byte-aligned packed relocation" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - - const S = struct { - var global: u8 align(2) = 0; - var packed_value: packed struct { x: u8, y: *align(2) u8 } = .{ .x = 111, .y = &global }; - }; - try expect(S.packed_value.x == 111); - try expect(S.packed_value.y == &S.global); -} - test "packed struct store of comparison result" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/packed-union.zig b/test/behavior/packed-union.zig index bbb2f612b6..f625c8b073 100644 --- a/test/behavior/packed-union.zig +++ b/test/behavior/packed-union.zig @@ -177,15 +177,3 @@ test "assigning to non-active field at comptime" { test_bits.bits = .{}; } } - -test "comptime packed union of pointers" { - const U = packed union { - a: *const u32, - b: *const [1]u32, - }; - - const x: u32 = 123; - const u: U = .{ .a = &x }; - - comptime assert(u.b[0] == 123); -} diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 1760f02c22..9badc9dabd 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -217,26 +217,6 @@ test "union with specified enum tag" { try comptime doTest(); } -test "packed union generates correctly aligned type" { - // This test will be removed after the following accepted proposal is implemented: - // https://github.com/ziglang/zig/issues/24657 - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - - const U = packed union { - f1: *const fn () error{TestUnexpectedResult}!void, - f2: usize, - }; - var foo = [_]U{ - U{ .f1 = doTest }, - U{ .f2 = 0 }, - }; - try foo[0].f1(); -} - fn doTest() error{TestUnexpectedResult}!void { try expect((try bar(Payload{ .A = 1234 })) == -10); } @@ -359,12 +339,12 @@ test "simple union(enum(u32))" { try expect(@intFromEnum(@as(Tag(MultipleChoice), x)) == 60); } -const PackedPtrOrInt = packed union { - ptr: *u8, - int: usize, -}; test "packed union size" { - comptime assert(@sizeOf(PackedPtrOrInt) == @sizeOf(usize)); + const U = packed union { + signed: isize, + unsigned: usize, + }; + comptime assert(@sizeOf(U) == @sizeOf(usize)); } const ZeroBits = union { diff --git a/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig b/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig index b5bf3d6f3a..5f4482421d 100644 --- a/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig +++ b/test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig @@ -76,6 +76,11 @@ export fn entry14() void { x: E, }); } +export fn entry15() void { + _ = @sizeOf(packed struct { + x: *const u32, + }); +} // error // @@ -103,3 +108,6 @@ export fn entry14() void { // :70:12: note: types are not available at runtime // :76:12: error: packed structs cannot contain fields of type 'tmp.entry14.E' // :74:15: note: enum declared here +// :81:12: error: packed structs cannot contain fields of type '*const u32' +// :81:12: note: pointers cannot be directly bitpacked +// :81:12: note: consider using 'usize' and '@intFromPtr' diff --git a/test/cases/compile_errors/packed_union_with_automatic_layout_field.zig b/test/cases/compile_errors/packed_union_with_automatic_layout_field.zig deleted file mode 100644 index c37e987c1c..0000000000 --- a/test/cases/compile_errors/packed_union_with_automatic_layout_field.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Foo = struct { - a: u32, - b: f32, -}; -const Payload = packed union { - A: Foo, - B: bool, -}; -export fn entry() void { - const a: Payload = .{ .B = true }; - _ = a; -} - -// error -// -// :6:8: error: packed unions cannot contain fields of type 'tmp.Foo' -// :6:8: note: only packed structs layout are allowed in packed types -// :1:13: note: struct declared here diff --git a/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig b/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig new file mode 100644 index 0000000000..cfbdf4e90a --- /dev/null +++ b/test/cases/compile_errors/packed_union_with_fields_of_not_allowed_types.zig @@ -0,0 +1,20 @@ +export fn entry0() void { + _ = @sizeOf(packed union { + foo: struct { a: u32 }, + bar: bool, + }); +} +export fn entry1() void { + _ = @sizeOf(packed union { + x: *const u32, + }); +} + +// error +// +// :3:14: error: packed unions cannot contain fields of type 'packed_union_with_fields_of_not_allowed_types.entry0__union_180__struct_182' +// :3:14: note: non-packed structs do not have a bit-packed representation +// :3:14: note: struct declared here +// :9:12: error: packed unions cannot contain fields of type '*const u32' +// :9:12: note: pointers cannot be directly bitpacked +// :9:12: note: consider using 'usize' and '@intFromPtr'