| author | |
| committer | |
| log | be9b42d7074077eadf18e8d934c6f22051397a72 |
| tree | 10f8788abd89af5dedcd9c3a371ab9f32b30f5e7 |
| parent | b4ffb402c082605c4b324e88120306fc8fb3cf32 |
This was already possible in practice by just wrapping a packed union into
a packed struct. Now it's also possible without doing that.5 files changed, 43 insertions(+), 3 deletions(-)
doc/langref.html.in+7| ... | ... | @@ -2513,6 +2513,13 @@ or |
| 2513 | 2513 | <p>A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible |
| 2514 | 2514 | to be in a {#link|packed struct#}.</p> |
| 2515 | 2515 | <p>All fields in a packed union must have the same {#link|@bitSizeOf#}.</p> |
| 2516 | ||
| 2517 | <p> | |
| 2518 | Equating packed unions results in a comparison of the backing integer, | |
| 2519 | and only works for the {#syntax#}=={#endsyntax#} and {#syntax#}!={#endsyntax#} {#link|Operators#}. | |
| 2520 | </p> | |
| 2521 | {#code|test_packed_union_equality.zig#} | |
| 2522 | ||
| 2516 | 2523 | {#header_close#} |
| 2517 | 2524 | |
| 2518 | 2525 | {#header_open|Anonymous Union Literals#} |
doc/langref/test_packed_union_equality.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | const std = @import("std"); | |
| 2 | const expectEqual = std.testing.expectEqual; | |
| 3 | ||
| 4 | test "packed union equality" { | |
| 5 | const U = packed union { | |
| 6 | a: u4, | |
| 7 | b: i4, | |
| 8 | }; | |
| 9 | const x: U = .{ .a = 3 }; | |
| 10 | const y: U = .{ .b = 3 }; | |
| 11 | try expectEqual(x, y); | |
| 12 | } | |
| 13 | ||
| 14 | // test |
src/Type.zig+1-2| ... | ... | @@ -334,11 +334,10 @@ pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool { |
| 334 | 334 | .undefined, |
| 335 | 335 | .null, |
| 336 | 336 | .error_union, |
| 337 | .@"union", | |
| 338 | 337 | .frame, |
| 339 | 338 | => false, |
| 340 | 339 | |
| 341 | .@"struct" => is_equality_cmp and ty.containerLayout(zcu) == .@"packed", | |
| 340 | .@"struct", .@"union" => is_equality_cmp and ty.containerLayout(zcu) == .@"packed", | |
| 342 | 341 | .pointer => !ty.isSlice(zcu) and (is_equality_cmp or ty.isCPtr(zcu)), |
| 343 | 342 | .optional => { |
| 344 | 343 | if (!is_equality_cmp) return false; |
src/codegen/llvm.zig+1-1| ... | ... | @@ -5750,7 +5750,7 @@ pub const FuncGen = struct { |
| 5750 | 5750 | return phi.toValue(); |
| 5751 | 5751 | }, |
| 5752 | 5752 | .float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }), |
| 5753 | .@"struct" => scalar_ty.bitpackBackingInt(zcu), | |
| 5753 | .@"struct", .@"union" => scalar_ty.bitpackBackingInt(zcu), | |
| 5754 | 5754 | else => unreachable, |
| 5755 | 5755 | }; |
| 5756 | 5756 | const is_signed = int_ty.isSignedInt(zcu); |
test/behavior/packed-union.zig+20| ... | ... | @@ -199,3 +199,23 @@ test "packed union with explicit backing integer" { |
| 199 | 199 | try U.check(.{ .raw = -2 }); |
| 200 | 200 | try comptime U.check(.{ .raw = -2 }); |
| 201 | 201 | } |
| 202 | ||
| 203 | test "packed union equality" { | |
| 204 | const Foo = packed union { | |
| 205 | a: u4, | |
| 206 | b: i4, | |
| 207 | }; | |
| 208 | ||
| 209 | const S = struct { | |
| 210 | fn doTest(x: Foo, y: Foo) !void { | |
| 211 | try expect(x == y); | |
| 212 | try expect(!(x != y)); | |
| 213 | } | |
| 214 | }; | |
| 215 | ||
| 216 | const x: Foo = .{ .a = 3 }; | |
| 217 | const y: Foo = .{ .b = 3 }; | |
| 218 | ||
| 219 | try S.doTest(x, y); | |
| 220 | comptime try S.doTest(x, y); | |
| 221 | } |