╭ packed-union.zig ─────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
.. conflicting_externs/ hasdecl/ import/ namespace_depends_on_compile_var/ pub_enum/ x86_64/ zon/ abs.zig addrspace_and_linksection.zig align.zig alignof.zig array.zig asm.zig atomics.zig backing_int.zig basic.zig bit_shifting.zig bitcast.zig bitreverse.zig bool.zig builtin_functions_returning_void_ byteswap.zig byval_arg_var.zig call.zig cast.zig cast_int.zig comptime_memory.zig const_slice_child.zig decl_literals.zig decltest.zig defer.zig destructure.zig duplicated_test_names.zig enum.zig error.zig eval.zig export_builtin.zig export_c_keywords.zig export_keyword.zig export_self_referential_type_info extern.zig extern_struct_zero_size_fields.zi field_parent_ptr.zig file_to_embed.txt floatop.zig fn.zig fn_delegation.zig fn_in_struct_in_comptime.zig for.zig generics.zig globals.zig hasdecl.zig hasfield.zig if.zig import.zig import_c_keywords.zig incomplete_struct_param_tld.zig inline_switch.zig int128.zig int_comparison_elision.zig ir_block_deps.zig lower_strlit_to_vector.zig math.zig maximum_minimum.zig member_func.zig memcpy.zig memmove.zig memset.zig merge_error_sets.zig muladd.zig multiple_externs_with_conflicting namespace_depends_on_compile_var. nan.zig null.zig optional.zig overlapping_assign.zig packed-struct.zig ╭─────────────────────────────────╮ │packed-union.zig │ ╰─────────────────────────────────╯ packed_struct_explicit_backing_in pointers.zig popcount.zig prefetch.zig ptrcast.zig ptrfromint.zig pub_enum.zig ref_var_in_if_after_if_2nd_switch reflection.zig return_address.zig saturating_arithmetic.zig select.zig shuffle.zig sizeof_and_typeof.zig slice.zig slice_sentinel_comptime.zig spirv.zig splat.zig src.zig string_literals.zig struct.zig struct_contains_null_ptr_itself.z struct_contains_slice_of_itself.z switch.zig switch_loop.zig switch_on_captured_error.zig switch_prong_err_enum.zig switch_prong_implicit_cast.zig this.zig threadlocal.zig truncate.zig try.zig tuple.zig tuple_declarations.zig type.zig type_info.zig typename.zig undefined.zig underscore.zig union.zig var_args.zig vector.zig void.zig wasm.zig while.zig widening.zig wrapping_arithmetic.zig x86_64.zig zero.bin zon.zig
1 const std = @import("std"); 2 const builtin = @import("builtin"); 3 const assert = std.debug.assert; 4 const expect = std.testing.expect; 5 const expectEqual = std.testing.expectEqual; 6 7 test "flags in packed union" { 8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 10 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; 11 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 12 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO 13 14 try testFlagsInPackedUnion(); 15 try comptime testFlagsInPackedUnion(); 16 } 17 18 fn testFlagsInPackedUnion() !void { 19 const FlagBits = packed struct(u8) { 20 enable_1: bool = false, 21 enable_2: bool = false, 22 enable_3: bool = false, 23 enable_4: bool = false, 24 other_flags: packed union { 25 flags: packed struct(u4) { 26 enable_1: bool = true, 27 enable_2: bool = false, 28 enable_3: bool = false, 29 enable_4: bool = false, 30 }, 31 bits: u4, 32 } = .{ .flags = .{} }, 33 }; 34 var test_bits: FlagBits = .{}; 35 36 try expectEqual(false, test_bits.enable_1); 37 try expectEqual(true, test_bits.other_flags.flags.enable_1); 38 39 test_bits.enable_1 = true; 40 41 try expectEqual(true, test_bits.enable_1); 42 try expectEqual(true, test_bits.other_flags.flags.enable_1); 43 44 test_bits.other_flags.flags.enable_1 = false; 45 46 try expectEqual(true, test_bits.enable_1); 47 try expectEqual(false, test_bits.other_flags.flags.enable_1); 48 } 49 50 test "flags in packed union at offset" { 51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; 53 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; 54 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 55 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO 56 57 try testFlagsInPackedUnionAtOffset(); 58 try comptime testFlagsInPackedUnionAtOffset(); 59 } 60 61 fn testFlagsInPackedUnionAtOffset() !void { 62 const FlagBits = packed union { 63 base_flags: packed struct(u12) { 64 a: packed union { 65 flags: packed struct(u4) { 66 enable_1: bool = true, 67 enable_2: bool = false, 68 enable_3: bool = false, 69 enable_4: bool = false, 70 }, 71 bits: u4, 72 }, 73 pad: u8 = 0, 74 }, 75 adv_flags: packed struct(u12) { 76 pad: u8 = 0, 77 adv: packed union { 78 flags: packed struct(u4) { 79 enable_1: bool = true, 80 enable_2: bool = false, 81 enable_3: bool = false, 82 enable_4: bool = false, 83 }, 84 bits: u4, 85 }, 86 }, 87 }; 88 var test_bits: FlagBits = .{ .adv_flags = .{ .adv = .{ .flags = .{} } } }; 89 90 try expectEqual(@as(u8, 0), test_bits.adv_flags.pad); 91 try expectEqual(true, test_bits.adv_flags.adv.flags.enable_1); 92 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_2); 93 94 test_bits.adv_flags.adv.flags.enable_1 = false; 95 test_bits.adv_flags.adv.flags.enable_2 = true; 96 try expectEqual(@as(u8, 0), test_bits.adv_flags.pad); 97 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_1); 98 try expectEqual(true, test_bits.adv_flags.adv.flags.enable_2); 99 100 test_bits.adv_flags.adv.bits = 12; 101 try expectEqual(@as(u8, 0), test_bits.adv_flags.pad); 102 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_1); 103 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_2); 104 } 105 106 // Originally reported at https://github.com/ziglang/zig/issues/16581 107 test "packed union in packed struct" { 108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 109 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 110 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 111 112 try testPackedUnionInPackedStruct(); 113 try comptime testPackedUnionInPackedStruct(); 114 } 115 116 fn testPackedUnionInPackedStruct() !void { 117 const ReadRequest = packed struct { key: i32 }; 118 const RequestType = enum(u1) { 119 read, 120 insert, 121 }; 122 const RequestUnion = packed union { 123 read: ReadRequest, 124 }; 125 126 const Request = packed struct { 127 active_type: RequestType, 128 request: RequestUnion, 129 const Self = @This(); 130 131 fn init(read: ReadRequest) Self { 132 return .{ 133 .active_type = .read, 134 .request = RequestUnion{ .read = read }, 135 }; 136 } 137 }; 138 139 try std.testing.expectEqual(RequestType.read, Request.init(.{ .key = 3 }).active_type); 140 } 141 142 test "packed union initialized with a runtime value" { 143 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO 145 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO 146 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 147 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 148 149 const Fields = packed struct { 150 timestamp: u50, 151 random_bits: u13, 152 }; 153 const ID = packed union { 154 value: u63, 155 fields: Fields, 156 157 fn getValue() i64 { 158 return 1341; 159 } 160 }; 161 162 const timestamp: i64 = ID.getValue(); 163 const id = ID{ .fields = Fields{ 164 .timestamp = @as(u50, @intCast(timestamp)), 165 .random_bits = 420, 166 } }; 167 try std.testing.expect((ID{ .value = id.value }).fields.timestamp == timestamp); 168 } 169 170 test "assigning to non-active field at comptime" { 171 comptime { 172 const FlagBits = packed union { 173 flags: packed struct {}, 174 bits: packed struct {}, 175 }; 176 177 var test_bits: FlagBits = .{ .flags = .{} }; 178 test_bits.bits = .{}; 179 } 180 } 181 182 test "packed union with explicit backing integer" { 183 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; 184 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; 185 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 186 187 const U = packed union(i32) { 188 raw: i32, 189 unsigned_halves: packed struct { low: u16, high: u16 }, 190 191 fn check(val: @This()) !void { 192 try expect(@as(i32, @bitCast(val)) == -2); 193 try expect(@as(u32, @bitCast(val)) == 0xFFFFFFFE); 194 try expect(val.raw == -2); 195 try expect(val.unsigned_halves.low == 0xFFFE); 196 try expect(val.unsigned_halves.high == 0xFFFF); 197 } 198 }; 199 try U.check(.{ .raw = -2 }); 200 try comptime U.check(.{ .raw = -2 }); 201 } 202 203 test "packed union equality" { 204 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 205 206 const Foo = packed union { 207 a: u4, 208 b: i4, 209 }; 210 211 const S = struct { 212 fn doTest(x: Foo, y: Foo) !void { 213 try expect(x == y); 214 try expect(!(x != y)); 215 } 216 }; 217 218 const x: Foo = .{ .a = 3 }; 219 const y: Foo = .{ .b = 3 }; 220 221 try S.doTest(x, y); 222 comptime try S.doTest(x, y); 223 } 224 225 test "initialize packed union field to undefined at comptime" { 226 const U = packed union(u8) { x: u8 }; 227 const val: U = .{ .x = undefined }; 228 _ = val; 229 } 230 231 test "convert from/to backing int" { 232 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 233 234 const U = packed union(u10) { 235 a: i10, 236 b: enum(u10) { x, y, z }, 237 fn doTheTest(u: @This()) !void { 238 const backing_int = @backingInt(u); 239 const reconstructed: @This() = @fromBackingInt(backing_int); 240 try expect(reconstructed == u); 241 } 242 }; 243 try U.doTheTest(.{ .a = 123 }); 244 try comptime U.doTheTest(.{ .a = 123 }); 245 } 246 247 test "equality with wide backing integer" { 248 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35982 249 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; 250 251 const U = packed union(i200) { 252 x: u200, 253 fn doTheTest(s: @This(), int: i200) !void { 254 try expect(s == @as(@This(), @bitCast(int))); 255 } 256 }; 257 try U.doTheTest(.{ .x = (1 << 200) - 1 }, -1); 258 try comptime U.doTheTest(.{ .x = (1 << 200) - 1 }, -1); 259 } 260