Commit e47706f344

Veikka Tuominen <git@vexu.eu>
2022-07-28 20:03:10
Sema: validate packed struct field types
1 parent f1768b4
src/Sema.zig
@@ -5049,13 +5049,13 @@ pub fn analyzeExport(
     try mod.ensureDeclAnalyzed(exported_decl_index);
     const exported_decl = mod.declPtr(exported_decl_index);
 
-    if (!(try sema.validateExternType(exported_decl.ty, .other))) {
+    if (!sema.validateExternType(exported_decl.ty, .other)) {
         const msg = msg: {
             const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});
             errdefer msg.destroy(sema.gpa);
 
             const src_decl = sema.mod.declPtr(block.src_decl);
-            try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
+            try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
 
             try sema.addDeclaredHereNote(msg, exported_decl.ty);
             break :msg msg;
@@ -7634,7 +7634,7 @@ fn funcCommon(
             };
             return sema.failWithOwnedErrorMsg(block, msg);
         }
-        if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !(try sema.validateExternType(return_type, .ret_ty))) {
+        if (!Type.fnCallingConventionAllowsZigTypes(cc_workaround) and !sema.validateExternType(return_type, .ret_ty)) {
             const msg = msg: {
                 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
                     return_type.fmt(sema.mod), @tagName(cc_workaround),
@@ -7642,7 +7642,7 @@ fn funcCommon(
                 errdefer msg.destroy(sema.gpa);
 
                 const src_decl = sema.mod.declPtr(block.src_decl);
-                try sema.explainWhyTypeIsNotExtern(block, ret_ty_src, msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
+                try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
 
                 try sema.addDeclaredHereNote(msg, return_type);
                 break :msg msg;
@@ -7830,7 +7830,7 @@ fn analyzeParameter(
         };
         return sema.failWithOwnedErrorMsg(block, msg);
     }
-    if (!Type.fnCallingConventionAllowsZigTypes(cc) and !(try sema.validateExternType(param.ty, .param_ty))) {
+    if (!Type.fnCallingConventionAllowsZigTypes(cc) and !sema.validateExternType(param.ty, .param_ty)) {
         const msg = msg: {
             const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
                 param.ty.fmt(sema.mod), @tagName(cc),
@@ -7838,7 +7838,7 @@ fn analyzeParameter(
             errdefer msg.destroy(sema.gpa);
 
             const src_decl = sema.mod.declPtr(block.src_decl);
-            try sema.explainWhyTypeIsNotExtern(block, param_src, msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
+            try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
 
             try sema.addDeclaredHereNote(msg, param.ty);
             break :msg msg;
@@ -14866,13 +14866,13 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
     } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
         return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
     } else if (inst_data.size == .C) {
-        if (!(try sema.validateExternType(elem_ty, .other))) {
+        if (!sema.validateExternType(elem_ty, .other)) {
             const msg = msg: {
                 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
                 errdefer msg.destroy(sema.gpa);
 
                 const src_decl = sema.mod.declPtr(block.src_decl);
-                try sema.explainWhyTypeIsNotExtern(block, elem_ty_src, msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
+                try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
 
                 try sema.addDeclaredHereNote(msg, elem_ty);
                 break :msg msg;
@@ -15950,13 +15950,13 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
             } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {
                 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
             } else if (ptr_size == .C) {
-                if (!(try sema.validateExternType(elem_ty, .other))) {
+                if (!sema.validateExternType(elem_ty, .other)) {
                     const msg = msg: {
                         const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
                         errdefer msg.destroy(sema.gpa);
 
                         const src_decl = sema.mod.declPtr(block.src_decl);
-                        try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), elem_ty, .other);
+                        try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), elem_ty, .other);
 
                         try sema.addDeclaredHereNote(msg, elem_ty);
                         break :msg msg;
@@ -19736,7 +19736,7 @@ const ExternPosition = enum {
 
 /// Returns true if `ty` is allowed in extern types.
 /// Does *NOT* require `ty` to be resolved in any way.
-fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileError!bool {
+fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) bool {
     switch (ty.zigTypeTag()) {
         .Type,
         .ComptimeFloat,
@@ -19781,8 +19781,6 @@ fn validateExternType(sema: *Sema, ty: Type, position: ExternPosition) CompileEr
 
 fn explainWhyTypeIsNotExtern(
     sema: *Sema,
-    block: *Block,
-    src: LazySrcLoc,
     msg: *Module.ErrorMsg,
     src_loc: Module.SrcLoc,
     ty: Type,
@@ -19826,7 +19824,7 @@ fn explainWhyTypeIsNotExtern(
             var buf: Type.Payload.Bits = undefined;
             const tag_ty = ty.intTagType(&buf);
             try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
-            try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, tag_ty, position);
+            try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
         },
         .Struct => try mod.errNoteNonLazy(src_loc, msg, "only structs with packed or extern layout are extern compatible", .{}),
         .Union => try mod.errNoteNonLazy(src_loc, msg, "only unions with packed or extern layout are extern compatible", .{}),
@@ -19836,13 +19834,87 @@ fn explainWhyTypeIsNotExtern(
             } else if (position == .param_ty) {
                 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
             }
-            try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position);
+            try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position);
         },
-        .Vector => try sema.explainWhyTypeIsNotExtern(block, src, msg, src_loc, ty.elemType2(), position),
+        .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), position),
         .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
     }
 }
 
+/// Returns true if `ty` is allowed in packed types.
+/// Does *NOT* require `ty` to be resolved in any way.
+fn validatePackedType(ty: Type) bool {
+    switch (ty.zigTypeTag()) {
+        .Type,
+        .ComptimeFloat,
+        .ComptimeInt,
+        .EnumLiteral,
+        .Undefined,
+        .Null,
+        .ErrorUnion,
+        .ErrorSet,
+        .BoundFn,
+        .Frame,
+        .NoReturn,
+        .Opaque,
+        .AnyFrame,
+        .Fn,
+        .Array,
+        .Optional,
+        => return false,
+        .Void,
+        .Bool,
+        .Float,
+        .Pointer,
+        .Int,
+        .Vector,
+        .Enum,
+        => return true,
+        .Struct, .Union => return ty.containerLayout() == .Packed,
+    }
+}
+
+fn explainWhyTypeIsNotPacked(
+    sema: *Sema,
+    msg: *Module.ErrorMsg,
+    src_loc: Module.SrcLoc,
+    ty: Type,
+) CompileError!void {
+    const mod = sema.mod;
+    switch (ty.zigTypeTag()) {
+        .Void,
+        .Bool,
+        .Float,
+        .Pointer,
+        .Int,
+        .Vector,
+        .Enum,
+        => return,
+        .Type,
+        .ComptimeFloat,
+        .ComptimeInt,
+        .EnumLiteral,
+        .Undefined,
+        .Null,
+        .BoundFn,
+        .Frame,
+        .NoReturn,
+        .Opaque,
+        .ErrorUnion,
+        .ErrorSet,
+        .AnyFrame,
+        .Optional,
+        .Array,
+        => try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{}),
+        .Fn => {
+            try mod.errNoteNonLazy(src_loc, msg, "type has no guaranteed in-memory representation", .{});
+            try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
+        },
+        .Struct => try mod.errNoteNonLazy(src_loc, msg, "only packed structs layout are allowed in packed types", .{}),
+        .Union => try mod.errNoteNonLazy(src_loc, msg, "only packed unions layout are allowed in packed types", .{}),
+    }
+}
+
 pub const PanicId = enum {
     unreach,
     unwrap_null,
@@ -26919,28 +26991,41 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
         const field = &struct_obj.fields.values()[i];
         field.ty = try field_ty.copy(decl_arena_allocator);
 
-        if (struct_obj.layout == .Extern and !(try sema.validateExternType(field.ty, .other))) {
+        if (field_ty.zigTypeTag() == .Opaque) {
+            const msg = msg: {
+                const tree = try sema.getAstTree(&block_scope);
+                const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
+                const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
+                errdefer msg.destroy(sema.gpa);
+
+                try sema.addDeclaredHereNote(msg, field_ty);
+                break :msg msg;
+            };
+            return sema.failWithOwnedErrorMsg(&block_scope, msg);
+        }
+        if (struct_obj.layout == .Extern and !sema.validateExternType(field.ty, .other)) {
             const msg = msg: {
                 const tree = try sema.getAstTree(&block_scope);
                 const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
                 const msg = try sema.errMsg(&block_scope, fields_src, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
                 errdefer msg.destroy(sema.gpa);
 
-                try sema.explainWhyTypeIsNotExtern(&block_scope, fields_src, msg, fields_src.toSrcLoc(decl), field.ty, .other);
+                try sema.explainWhyTypeIsNotExtern(msg, fields_src.toSrcLoc(decl), field.ty, .other);
 
                 try sema.addDeclaredHereNote(msg, field.ty);
                 break :msg msg;
             };
             return sema.failWithOwnedErrorMsg(&block_scope, msg);
-        }
-        if (field_ty.zigTypeTag() == .Opaque) {
+        } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
             const msg = msg: {
                 const tree = try sema.getAstTree(&block_scope);
-                const field_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
-                const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
+                const fields_src = enumFieldSrcLoc(decl, tree.*, struct_obj.node_offset, i);
+                const msg = try sema.errMsg(&block_scope, fields_src, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
                 errdefer msg.destroy(sema.gpa);
 
-                try sema.addDeclaredHereNote(msg, field_ty);
+                try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field.ty);
+
+                try sema.addDeclaredHereNote(msg, field.ty);
                 break :msg msg;
             };
             return sema.failWithOwnedErrorMsg(&block_scope, msg);
@@ -27243,27 +27328,40 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
             }
         }
 
-        if (union_obj.layout == .Extern and !(try sema.validateExternType(field_ty, .union_field))) {
+        if (field_ty.zigTypeTag() == .Opaque) {
             const msg = msg: {
                 const tree = try sema.getAstTree(&block_scope);
                 const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
-                const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
+                const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
                 errdefer msg.destroy(sema.gpa);
 
-                try sema.explainWhyTypeIsNotExtern(&block_scope, field_src, msg, field_src.toSrcLoc(decl), field_ty, .union_field);
-
                 try sema.addDeclaredHereNote(msg, field_ty);
                 break :msg msg;
             };
             return sema.failWithOwnedErrorMsg(&block_scope, msg);
         }
-        if (field_ty.zigTypeTag() == .Opaque) {
+        if (union_obj.layout == .Extern and !sema.validateExternType(field_ty, .union_field)) {
             const msg = msg: {
                 const tree = try sema.getAstTree(&block_scope);
                 const field_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
-                const msg = try sema.errMsg(&block_scope, field_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
+                const msg = try sema.errMsg(&block_scope, field_src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
                 errdefer msg.destroy(sema.gpa);
 
+                try sema.explainWhyTypeIsNotExtern(msg, field_src.toSrcLoc(decl), field_ty, .union_field);
+
+                try sema.addDeclaredHereNote(msg, field_ty);
+                break :msg msg;
+            };
+            return sema.failWithOwnedErrorMsg(&block_scope, msg);
+        } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
+            const msg = msg: {
+                const tree = try sema.getAstTree(&block_scope);
+                const fields_src = enumFieldSrcLoc(decl, tree.*, union_obj.node_offset, field_i);
+                const msg = try sema.errMsg(&block_scope, fields_src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
+                errdefer msg.destroy(sema.gpa);
+
+                try sema.explainWhyTypeIsNotPacked(msg, fields_src.toSrcLoc(decl), field_ty);
+
                 try sema.addDeclaredHereNote(msg, field_ty);
                 break :msg msg;
             };
test/behavior/packed-struct.zig
@@ -6,6 +6,8 @@ const expectEqual = std.testing.expectEqual;
 const native_endian = builtin.cpu.arch.endian();
 
 test "correct size of packed structs" {
+    // Stage2 has different packed struct semantics.
+    if (builtin.zig_backend != .stage1) return error.SkipZigTest;
     const T1 = packed struct { one: u8, three: [3]u8 };
 
     try expectEqual(4, @sizeOf(T1));
@@ -118,18 +120,6 @@ test "flags in packed structs" {
     try expectEqual(32, @bitSizeOf(Flags3));
 }
 
-test "arrays in packed structs" {
-    if (builtin.zig_backend == .stage1) return error.SkipZigTest;
-
-    const T1 = packed struct { array: [3][3]u8 };
-    const T2 = packed struct { array: [9]u8 };
-
-    try expectEqual(@sizeOf(u72), @sizeOf(T1));
-    try expectEqual(72, @bitSizeOf(T1));
-    try expectEqual(@sizeOf(u72), @sizeOf(T2));
-    try expectEqual(72, @bitSizeOf(T2));
-}
-
 test "consistent size of packed structs" {
     if (builtin.zig_backend == .stage1) return error.SkipZigTest;
 
@@ -145,23 +135,15 @@ test "consistent size of packed structs" {
     try expectEqual(register_size_bits, @bitSizeOf(TxData2));
     try expectEqual(register_size_bytes, @sizeOf(TxData2));
 
-    const TxData3 = packed struct { a: u32, b: [3]u8 };
     const TxData4 = packed struct { a: u32, b: u24 };
-    const TxData5 = packed struct { a: [3]u8, b: u32 };
     const TxData6 = packed struct { a: u24, b: u32 };
 
     const expectedBitSize = 56;
     const expectedByteSize = @sizeOf(u56);
 
-    try expectEqual(expectedBitSize, @bitSizeOf(TxData3));
-    try expectEqual(expectedByteSize, @sizeOf(TxData3));
-
     try expectEqual(expectedBitSize, @bitSizeOf(TxData4));
     try expectEqual(expectedByteSize, @sizeOf(TxData4));
 
-    try expectEqual(expectedBitSize, @bitSizeOf(TxData5));
-    try expectEqual(expectedByteSize, @sizeOf(TxData5));
-
     try expectEqual(expectedBitSize, @bitSizeOf(TxData6));
     try expectEqual(expectedByteSize, @sizeOf(TxData6));
 }
@@ -234,12 +216,6 @@ test "correct sizeOf and offsets in packed structs" {
         try expectEqual(@as(u7, 0b1111010), s2.y);
         try expectEqual(@as(u24, 0xd5c71f), s2.z);
     }
-
-    const S = packed struct { a: u32, pad: [3]u32, b: u32 };
-
-    try expectEqual(16, @offsetOf(S, "b"));
-    try expectEqual(128, @bitOffsetOf(S, "b"));
-    try expectEqual(@sizeOf(u160), @sizeOf(S));
 }
 
 test "nested packed structs" {
test/behavior/sizeof_and_typeof.zig
@@ -105,6 +105,8 @@ test "@offsetOf" {
 }
 
 test "@offsetOf packed struct, array length not power of 2 or multiple of native pointer width in bytes" {
+    // Stage2 has different packed struct semantics.
+    if (builtin.zig_backend != .stage1) return error.SkipZigTest;
     const p3a_len = 3;
     const P3 = packed struct {
         a: [p3a_len]u8,
test/behavior/struct.zig
@@ -704,10 +704,8 @@ const FooArray24Bits = packed struct {
 };
 
 test "aligned array of packed struct" {
-    if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    // Stage2 has different packed struct semantics.
+    if (builtin.zig_backend != .stage1) return error.SkipZigTest;
 
     comptime {
         try expect(@sizeOf(FooStructAligned) == 2);
test/cases/compile_errors/stage1/test/packed_struct_with_fields_of_not_allowed_types.zig
@@ -1,74 +0,0 @@
-const A = packed struct {
-    x: anyerror,
-};
-const B = packed struct {
-    x: [2]u24,
-};
-const C = packed struct {
-    x: [1]anyerror,
-};
-const D = packed struct {
-    x: [1]S,
-};
-const E = packed struct {
-    x: [1]U,
-};
-const F = packed struct {
-    x: ?anyerror,
-};
-const G = packed struct {
-    x: Enum,
-};
-export fn entry1() void {
-    var a: A = undefined;
-    _ = a;
-}
-export fn entry2() void {
-    var b: B = undefined;
-    _ = b;
-}
-export fn entry3() void {
-    var r: C = undefined;
-    _ = r;
-}
-export fn entry4() void {
-    var d: D = undefined;
-    _ = d;
-}
-export fn entry5() void {
-    var e: E = undefined;
-    _ = e;
-}
-export fn entry6() void {
-    var f: F = undefined;
-    _ = f;
-}
-export fn entry7() void {
-    var g: G = undefined;
-    _ = g;
-}
-const S = struct {
-    x: i32,
-};
-const U = struct {
-    A: i32,
-    B: u32,
-};
-const Enum = enum {
-    A,
-    B,
-};
-
-// error
-// backend=stage1
-// target=native
-// is_test=1
-//
-// tmp.zig:2:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation
-// tmp.zig:5:5: error: array of 'u24' not allowed in packed struct due to padding bits (must be padded from 48 to 64 bits)
-// tmp.zig:8:5: error: type 'anyerror' not allowed in packed struct; no guaranteed in-memory representation
-// tmp.zig:11:5: error: non-packed, non-extern struct 'S' not allowed in packed struct; no guaranteed in-memory representation
-// tmp.zig:14:5: error: non-packed, non-extern struct 'U' not allowed in packed struct; no guaranteed in-memory representation
-// tmp.zig:17:5: error: type '?anyerror' not allowed in packed struct; no guaranteed in-memory representation
-// tmp.zig:20:5: error: type 'Enum' not allowed in packed struct; no guaranteed in-memory representation
-// tmp.zig:57:14: note: enum declaration does not specify an integer tag type
test/cases/compile_errors/packed_struct_with_fields_of_not_allowed_types.zig
@@ -0,0 +1,84 @@
+export fn entry1() void {
+    _ = @sizeOf(packed struct {
+        x: anyerror,
+    });
+}
+export fn entry2() void {
+    _ = @sizeOf(packed struct {
+        x: [2]u24,
+    });
+}
+export fn entry3() void {
+    _ = @sizeOf(packed struct {
+        x: anyerror!u32,
+    });
+}
+export fn entry4() void {
+    _ = @sizeOf(packed struct {
+        x: S,
+    });
+}
+export fn entry5() void {
+    _ = @sizeOf(packed struct {
+        x: U,
+    });
+}
+export fn entry6() void {
+    _ = @sizeOf(packed struct {
+        x: ?anyerror,
+    });
+}
+export fn entry7() void {
+    _ = @sizeOf(packed struct {
+        x: enum { A, B },
+    });
+}
+export fn entry8() void {
+    _ = @sizeOf(packed struct {
+        x: fn () void,
+    });
+}
+export fn entry9() void {
+    _ = @sizeOf(packed struct {
+        x: *const fn () void,
+    });
+}
+export fn entry10() void {
+    _ = @sizeOf(packed struct {
+        x: packed struct { x: i32 },
+    });
+}
+export fn entry11() void {
+    _ = @sizeOf(packed struct {
+        x: packed union { A: i32, B: u32 },
+    });
+}
+const S = struct {
+    x: i32,
+};
+const U = extern union {
+    A: i32,
+    B: u32,
+};
+
+// error
+// backend=llvm
+// target=native
+//
+// :3:9: error: packed structs cannot contain fields of type 'anyerror'
+// :3:9: note: type has no guaranteed in-memory representation
+// :8:9: error: packed structs cannot contain fields of type '[2]u24'
+// :8:9: note: type has no guaranteed in-memory representation
+// :13:9: error: packed structs cannot contain fields of type 'anyerror!u32'
+// :13:9: note: type has no guaranteed in-memory representation
+// :18:9: error: packed structs cannot contain fields of type 'tmp.S'
+// :18:9: note: only packed structs layout are allowed in packed types
+// :56:11: note: struct declared here
+// :23:9: error: packed structs cannot contain fields of type 'tmp.U'
+// :23:9: note: only packed unions layout are allowed in packed types
+// :59:18: note: union declared here
+// :28:9: error: packed structs cannot contain fields of type '?anyerror'
+// :28:9: note: type has no guaranteed in-memory representation
+// :38:9: error: packed structs cannot contain fields of type 'fn() void'
+// :38:9: note: type has no guaranteed in-memory representation
+// :38:9: note: use '*const ' to make a function pointer type