mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
Merge pull request 'Sema: implement switch for packed structs/unions' (#31464) from justusk/zig:packed-switch into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31464 Reviewed-by: Andrew Kelley <andrew@ziglang.org>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1327,3 +1327,135 @@ test "single range switch prong capture" {
|
||||
try S.doTheTest(2);
|
||||
try comptime S.doTheTest(2);
|
||||
}
|
||||
|
||||
test "switch on packed struct" {
|
||||
const P = packed struct {
|
||||
a: u1,
|
||||
b: u1,
|
||||
|
||||
fn doTheTest(p: @This()) !void {
|
||||
switch (p) {
|
||||
.{ .a = 0, .b = 1 } => {},
|
||||
else => return error.TestFailed,
|
||||
}
|
||||
|
||||
switch (p) {
|
||||
.{ .a = 0, .b = 1 } => {},
|
||||
.{ .a = 0, .b = 0 },
|
||||
.{ .a = 1, .b = 0 },
|
||||
.{ .a = 1, .b = 1 },
|
||||
=> return error.TestFailed,
|
||||
}
|
||||
|
||||
switch (p) {
|
||||
inline else => |val| {
|
||||
if (val != @This(){ .a = 0, .b = 1 }) return error.TestFailed;
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
try P.doTheTest(.{ .a = 0, .b = 1 });
|
||||
try comptime P.doTheTest(.{ .a = 0, .b = 1 });
|
||||
}
|
||||
|
||||
test "switch on packed union" {
|
||||
const P = packed union(u2) {
|
||||
a: u2,
|
||||
b: i2,
|
||||
c: packed struct(u2) { x: u1, y: i1 },
|
||||
|
||||
fn doTheTest(p: @This()) !void {
|
||||
switch (p) {
|
||||
.{ .a = 1 } => {},
|
||||
else => return error.TestFailed,
|
||||
}
|
||||
|
||||
switch (p) {
|
||||
.{ .a = 1 } => {},
|
||||
.{ .a = 0 },
|
||||
.{ .a = 2 },
|
||||
.{ .a = 3 },
|
||||
=> return error.TestFailed,
|
||||
}
|
||||
|
||||
switch (p) {
|
||||
.{ .a = 1 } => {},
|
||||
.{ .a = 0 },
|
||||
.{ .b = -2 },
|
||||
.{ .b = -1 },
|
||||
=> return error.TestFailed,
|
||||
}
|
||||
|
||||
switch (p) {
|
||||
.{ .c = .{ .x = 1, .y = 0 } } => {},
|
||||
.{ .b = 0 },
|
||||
.{ .a = 2 },
|
||||
.{ .c = .{ .x = 1, .y = -1 } },
|
||||
=> return error.TestFailed,
|
||||
}
|
||||
|
||||
switch (p) {
|
||||
inline else => |val| {
|
||||
if (val != @This(){ .c = .{ .x = 1, .y = 0 } }) return error.TestFailed;
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
try P.doTheTest(.{ .a = 1 });
|
||||
try comptime P.doTheTest(.{ .a = 1 });
|
||||
}
|
||||
|
||||
test "switch on nested packed containers" {
|
||||
if (builtin.object_format == .c) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31467
|
||||
|
||||
const P = packed struct {
|
||||
iu: u17,
|
||||
is: i31,
|
||||
b: bool,
|
||||
e: enum(u5) { a = 5, b = 3, c = 12 },
|
||||
un: packed union {
|
||||
a: i9,
|
||||
b: u9,
|
||||
c: packed struct(u9) { a: i5, b: u4 },
|
||||
},
|
||||
p: packed struct(u9) { a: u3, b: u6 },
|
||||
|
||||
fn doTheTest(p: @This()) !void {
|
||||
switch (p) {
|
||||
.{
|
||||
.iu = 72,
|
||||
.is = 124,
|
||||
.b = false,
|
||||
.e = .c,
|
||||
.un = .{ .b = 13 },
|
||||
.p = .{ .a = 0, .b = 12 },
|
||||
} => return error.TestFailed,
|
||||
.{
|
||||
.iu = 129,
|
||||
.is = -162784612,
|
||||
.b = true,
|
||||
.e = .a,
|
||||
.un = .{ .c = .{ .a = -3, .b = 9 } },
|
||||
.p = .{ .a = 2, .b = 17 },
|
||||
} => {},
|
||||
else => return error.TestFailed,
|
||||
}
|
||||
}
|
||||
};
|
||||
try P.doTheTest(.{
|
||||
.iu = 129,
|
||||
.is = -162784612,
|
||||
.b = true,
|
||||
.e = .a,
|
||||
.un = .{ .c = .{ .a = -3, .b = 9 } },
|
||||
.p = .{ .a = 2, .b = 17 },
|
||||
});
|
||||
try comptime P.doTheTest(.{
|
||||
.iu = 129,
|
||||
.is = -162784612,
|
||||
.b = true,
|
||||
.e = .a,
|
||||
.un = .{ .c = .{ .a = -3, .b = 9 } },
|
||||
.p = .{ .a = 2, .b = 17 },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -509,3 +509,58 @@ test "switch loop for error handling" {
|
||||
try S.doTheTest();
|
||||
try comptime S.doTheTest();
|
||||
}
|
||||
|
||||
test "switch loop with packed structs" {
|
||||
const P = packed struct {
|
||||
a: u7,
|
||||
b: u20,
|
||||
|
||||
fn doTheTest(p: @This()) !void {
|
||||
const result = s: switch (p) {
|
||||
.{ .a = 5, .b = 10 } => |x| x,
|
||||
else => |x| continue :s .{ .a = x.a, .b = x.b + 1 },
|
||||
};
|
||||
try expect(result == @This(){ .a = 5, .b = 10 });
|
||||
}
|
||||
};
|
||||
try P.doTheTest(.{ .a = 5, .b = 0 });
|
||||
try comptime P.doTheTest(.{ .a = 5, .b = 0 });
|
||||
}
|
||||
|
||||
test "switch loop with packed unions" {
|
||||
const P = packed union {
|
||||
a: u7,
|
||||
b: i7,
|
||||
|
||||
fn doTheTest(p: @This()) !void {
|
||||
const result = s: switch (p) {
|
||||
.{ .a = 10 } => |x| x,
|
||||
else => |x| continue :s .{ .b = @intCast(x.a + 1) },
|
||||
};
|
||||
try expect(result == @This(){ .b = 10 });
|
||||
}
|
||||
};
|
||||
try P.doTheTest(.{ .a = 5 });
|
||||
try comptime P.doTheTest(.{ .a = 5 });
|
||||
}
|
||||
|
||||
test "switch loop with packed unions with OPV" {
|
||||
const P = packed union {
|
||||
a: u0,
|
||||
b: i0,
|
||||
|
||||
fn doTheTest(p: @This()) !void {
|
||||
var looped = false;
|
||||
s: switch (p) {
|
||||
.{ .b = 0 } => |x| {
|
||||
comptime assert(x.a == 0);
|
||||
if (looped) break :s;
|
||||
looped = true;
|
||||
continue :s .{ .a = 0 };
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
try P.doTheTest(.{ .a = 0 });
|
||||
try comptime P.doTheTest(.{ .a = 0 });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user