diff --git a/doc/langref.html.in b/doc/langref.html.in index 7118d01c9173a0544b8ba4030321125f49a62863..adac8f137fec86fe91b785d3375c326edb75460f 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2513,6 +2513,13 @@ or

A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible to be in a {#link|packed struct#}.

All fields in a packed union must have the same {#link|@bitSizeOf#}.

+ +

+ Equating packed unions results in a comparison of the backing integer, + and only works for the {#syntax#}=={#endsyntax#} and {#syntax#}!={#endsyntax#} {#link|Operators#}. +

+ {#code|test_packed_union_equality.zig#} + {#header_close#} {#header_open|Anonymous Union Literals#} diff --git a/doc/langref/test_packed_union_equality.zig b/doc/langref/test_packed_union_equality.zig new file mode 100644 index 0000000000000000000000000000000000000000..5ba69110ab445913225c19393800acbc0b44e193 --- /dev/null +++ b/doc/langref/test_packed_union_equality.zig @@ -0,0 +1,14 @@ +const std = @import("std"); +const expectEqual = std.testing.expectEqual; + +test "packed union equality" { + const U = packed union { + a: u4, + b: i4, + }; + const x: U = .{ .a = 3 }; + const y: U = .{ .b = 3 }; + try expectEqual(x, y); +} + +// test diff --git a/src/Type.zig b/src/Type.zig index 841ca38b0e536b79ca44817eb55941b864ac3f56..475fb09edd9101d99c8ec2b83f39bddef37a3c02 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -334,11 +334,10 @@ pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool { .undefined, .null, .error_union, - .@"union", .frame, => false, - .@"struct" => is_equality_cmp and ty.containerLayout(zcu) == .@"packed", + .@"struct", .@"union" => is_equality_cmp and ty.containerLayout(zcu) == .@"packed", .pointer => !ty.isSlice(zcu) and (is_equality_cmp or ty.isCPtr(zcu)), .optional => { if (!is_equality_cmp) return false; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 0907396630950b3130d47a4187f1687e77149ea7..7661d2fe52f4a51a4ca57ea1d4c56c511195b73d 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5750,7 +5750,7 @@ pub const FuncGen = struct { return phi.toValue(); }, .float => return self.buildFloatCmp(fast, op, operand_ty, .{ lhs, rhs }), - .@"struct" => scalar_ty.bitpackBackingInt(zcu), + .@"struct", .@"union" => scalar_ty.bitpackBackingInt(zcu), else => unreachable, }; const is_signed = int_ty.isSignedInt(zcu); diff --git a/test/behavior/packed-union.zig b/test/behavior/packed-union.zig index 330a4853b13383b05fc4b7363c8b35e916085d9f..fec142665737c166abd8ac921bec555cef85a530 100644 --- a/test/behavior/packed-union.zig +++ b/test/behavior/packed-union.zig @@ -199,3 +199,23 @@ test "packed union with explicit backing integer" { try U.check(.{ .raw = -2 }); try comptime U.check(.{ .raw = -2 }); } + +test "packed union equality" { + const Foo = packed union { + a: u4, + b: i4, + }; + + const S = struct { + fn doTest(x: Foo, y: Foo) !void { + try expect(x == y); + try expect(!(x != y)); + } + }; + + const x: Foo = .{ .a = 3 }; + const y: Foo = .{ .b = 3 }; + + try S.doTest(x, y); + comptime try S.doTest(x, y); +}