mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Some tests are now failing due to debug info changes, some tests now pass due to improved compiler functionality.
804 lines
21 KiB
Zig
804 lines
21 KiB
Zig
const builtin = @import("builtin");
|
|
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const expect = std.testing.expect;
|
|
const expectError = std.testing.expectError;
|
|
const expectEqual = std.testing.expectEqual;
|
|
|
|
test "switch with numbers" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testSwitchWithNumbers(13);
|
|
}
|
|
|
|
fn testSwitchWithNumbers(x: u32) !void {
|
|
const result = switch (x) {
|
|
1, 2, 3, 4...8 => false,
|
|
13 => true,
|
|
else => false,
|
|
};
|
|
try expect(result);
|
|
}
|
|
|
|
test "switch with all ranges" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try expect(testSwitchWithAllRanges(50, 3) == 1);
|
|
try expect(testSwitchWithAllRanges(101, 0) == 2);
|
|
try expect(testSwitchWithAllRanges(300, 5) == 3);
|
|
try expect(testSwitchWithAllRanges(301, 6) == 6);
|
|
}
|
|
|
|
fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
|
|
return switch (x) {
|
|
0...100 => 1,
|
|
101...200 => 2,
|
|
201...300 => 3,
|
|
else => y,
|
|
};
|
|
}
|
|
|
|
test "implicit comptime switch" {
|
|
const x = 3 + 4;
|
|
const result = switch (x) {
|
|
3 => 10,
|
|
4 => 11,
|
|
5, 6 => 12,
|
|
7, 8 => 13,
|
|
else => 14,
|
|
};
|
|
|
|
comptime {
|
|
try expect(result + 1 == 14);
|
|
}
|
|
}
|
|
|
|
test "switch on enum" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const fruit = Fruit.Orange;
|
|
nonConstSwitchOnEnum(fruit);
|
|
}
|
|
const Fruit = enum {
|
|
Apple,
|
|
Orange,
|
|
Banana,
|
|
};
|
|
fn nonConstSwitchOnEnum(fruit: Fruit) void {
|
|
switch (fruit) {
|
|
Fruit.Apple => unreachable,
|
|
Fruit.Orange => {},
|
|
Fruit.Banana => unreachable,
|
|
}
|
|
}
|
|
|
|
test "switch statement" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try nonConstSwitch(SwitchStatementFoo.C);
|
|
}
|
|
fn nonConstSwitch(foo: SwitchStatementFoo) !void {
|
|
const val = switch (foo) {
|
|
SwitchStatementFoo.A => @as(i32, 1),
|
|
SwitchStatementFoo.B => 2,
|
|
SwitchStatementFoo.C => 3,
|
|
SwitchStatementFoo.D => 4,
|
|
};
|
|
try expect(val == 3);
|
|
}
|
|
const SwitchStatementFoo = enum { A, B, C, D };
|
|
|
|
test "switch with multiple expressions" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const x = switch (returnsFive()) {
|
|
1, 2, 3 => 1,
|
|
4, 5, 6 => 2,
|
|
else => @as(i32, 3),
|
|
};
|
|
try expect(x == 2);
|
|
}
|
|
fn returnsFive() i32 {
|
|
return 5;
|
|
}
|
|
|
|
test "switch on type" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try expect(trueIfBoolFalseOtherwise(bool));
|
|
try expect(!trueIfBoolFalseOtherwise(i32));
|
|
}
|
|
|
|
fn trueIfBoolFalseOtherwise(comptime T: type) bool {
|
|
return switch (T) {
|
|
bool => true,
|
|
else => false,
|
|
};
|
|
}
|
|
|
|
test "switching on booleans" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
try testSwitchOnBools();
|
|
try comptime testSwitchOnBools();
|
|
}
|
|
|
|
fn testSwitchOnBools() !void {
|
|
try expect(testSwitchOnBoolsTrueAndFalse(true) == false);
|
|
try expect(testSwitchOnBoolsTrueAndFalse(false) == true);
|
|
|
|
try expect(testSwitchOnBoolsTrueWithElse(true) == false);
|
|
try expect(testSwitchOnBoolsTrueWithElse(false) == true);
|
|
|
|
try expect(testSwitchOnBoolsFalseWithElse(true) == false);
|
|
try expect(testSwitchOnBoolsFalseWithElse(false) == true);
|
|
}
|
|
|
|
fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
|
|
return switch (x) {
|
|
true => false,
|
|
false => true,
|
|
};
|
|
}
|
|
|
|
fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
|
|
return switch (x) {
|
|
true => false,
|
|
else => true,
|
|
};
|
|
}
|
|
|
|
fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
|
|
return switch (x) {
|
|
false => true,
|
|
else => false,
|
|
};
|
|
}
|
|
|
|
test "u0" {
|
|
var val: u0 = 0;
|
|
switch (val) {
|
|
0 => try expect(val == 0),
|
|
}
|
|
}
|
|
|
|
test "undefined.u0" {
|
|
var val: u0 = undefined;
|
|
switch (val) {
|
|
0 => try expect(val == 0),
|
|
}
|
|
}
|
|
|
|
test "switch with disjoint range" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
var q: u8 = 0;
|
|
switch (q) {
|
|
0...125 => {},
|
|
127...255 => {},
|
|
126...126 => {},
|
|
}
|
|
}
|
|
|
|
test "switch variable for range and multiple prongs" {
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var u: u8 = 16;
|
|
try doTheSwitch(u);
|
|
try comptime doTheSwitch(u);
|
|
var v: u8 = 42;
|
|
try doTheSwitch(v);
|
|
try comptime doTheSwitch(v);
|
|
}
|
|
fn doTheSwitch(q: u8) !void {
|
|
switch (q) {
|
|
0...40 => |x| try expect(x == 16),
|
|
41, 42, 43 => |x| try expect(x == 42),
|
|
else => try expect(false),
|
|
}
|
|
}
|
|
};
|
|
_ = S;
|
|
}
|
|
|
|
var state: u32 = 0;
|
|
fn poll() void {
|
|
switch (state) {
|
|
0 => {
|
|
state = 1;
|
|
},
|
|
else => {
|
|
state += 1;
|
|
},
|
|
}
|
|
}
|
|
|
|
test "switch on global mutable var isn't constant-folded" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
while (state < 2) {
|
|
poll();
|
|
}
|
|
}
|
|
|
|
const SwitchProngWithVarEnum = union(enum) {
|
|
One: i32,
|
|
Two: f32,
|
|
Meh: void,
|
|
};
|
|
|
|
test "switch prong with variable" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
|
|
try switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
|
|
try switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
|
|
}
|
|
fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
|
|
switch (a) {
|
|
SwitchProngWithVarEnum.One => |x| {
|
|
try expect(x == 13);
|
|
},
|
|
SwitchProngWithVarEnum.Two => |x| {
|
|
try expect(x == 13.0);
|
|
},
|
|
SwitchProngWithVarEnum.Meh => |x| {
|
|
const v: void = x;
|
|
_ = v;
|
|
},
|
|
}
|
|
}
|
|
|
|
test "switch on enum using pointer capture" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testSwitchEnumPtrCapture();
|
|
try comptime testSwitchEnumPtrCapture();
|
|
}
|
|
|
|
fn testSwitchEnumPtrCapture() !void {
|
|
var value = SwitchProngWithVarEnum{ .One = 1234 };
|
|
switch (value) {
|
|
SwitchProngWithVarEnum.One => |*x| x.* += 1,
|
|
else => unreachable,
|
|
}
|
|
switch (value) {
|
|
SwitchProngWithVarEnum.One => |x| try expect(x == 1235),
|
|
else => unreachable,
|
|
}
|
|
}
|
|
|
|
test "switch handles all cases of number" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testSwitchHandleAllCases();
|
|
try comptime testSwitchHandleAllCases();
|
|
}
|
|
|
|
fn testSwitchHandleAllCases() !void {
|
|
try expect(testSwitchHandleAllCasesExhaustive(0) == 3);
|
|
try expect(testSwitchHandleAllCasesExhaustive(1) == 2);
|
|
try expect(testSwitchHandleAllCasesExhaustive(2) == 1);
|
|
try expect(testSwitchHandleAllCasesExhaustive(3) == 0);
|
|
|
|
try expect(testSwitchHandleAllCasesRange(100) == 0);
|
|
try expect(testSwitchHandleAllCasesRange(200) == 1);
|
|
try expect(testSwitchHandleAllCasesRange(201) == 2);
|
|
try expect(testSwitchHandleAllCasesRange(202) == 4);
|
|
try expect(testSwitchHandleAllCasesRange(230) == 3);
|
|
}
|
|
|
|
fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
|
|
return switch (x) {
|
|
0 => @as(u2, 3),
|
|
1 => 2,
|
|
2 => 1,
|
|
3 => 0,
|
|
};
|
|
}
|
|
|
|
fn testSwitchHandleAllCasesRange(x: u8) u8 {
|
|
return switch (x) {
|
|
0...100 => @as(u8, 0),
|
|
101...200 => 1,
|
|
201, 203 => 2,
|
|
202 => 4,
|
|
204...255 => 3,
|
|
};
|
|
}
|
|
|
|
test "switch on union with some prongs capturing" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const X = union(enum) {
|
|
a,
|
|
b: i32,
|
|
};
|
|
|
|
var x: X = X{ .b = 10 };
|
|
var y: i32 = switch (x) {
|
|
.a => unreachable,
|
|
.b => |b| b + 1,
|
|
};
|
|
try expect(y == 11);
|
|
}
|
|
|
|
const Number = union(enum) {
|
|
One: u64,
|
|
Two: u8,
|
|
Three: f32,
|
|
};
|
|
|
|
const number = Number{ .Three = 1.23 };
|
|
|
|
fn returnsFalse() bool {
|
|
switch (number) {
|
|
Number.One => |x| return x > 1234,
|
|
Number.Two => |x| return x == 'a',
|
|
Number.Three => |x| return x > 12.34,
|
|
}
|
|
}
|
|
test "switch on const enum with var" {
|
|
try expect(!returnsFalse());
|
|
}
|
|
|
|
test "anon enum literal used in switch on union enum" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const Foo = union(enum) {
|
|
a: i32,
|
|
};
|
|
|
|
var foo = Foo{ .a = 1234 };
|
|
switch (foo) {
|
|
.a => |x| {
|
|
try expect(x == 1234);
|
|
},
|
|
}
|
|
}
|
|
|
|
test "switch all prongs unreachable" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
try testAllProngsUnreachable();
|
|
try comptime testAllProngsUnreachable();
|
|
}
|
|
|
|
fn testAllProngsUnreachable() !void {
|
|
try expect(switchWithUnreachable(1) == 2);
|
|
try expect(switchWithUnreachable(2) == 10);
|
|
}
|
|
|
|
fn switchWithUnreachable(x: i32) i32 {
|
|
while (true) {
|
|
switch (x) {
|
|
1 => return 2,
|
|
2 => break,
|
|
else => continue,
|
|
}
|
|
}
|
|
return 10;
|
|
}
|
|
|
|
test "capture value of switch with all unreachable prongs" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const x = return_a_number() catch |err| switch (err) {
|
|
else => unreachable,
|
|
};
|
|
try expect(x == 1);
|
|
}
|
|
|
|
fn return_a_number() anyerror!i32 {
|
|
return 1;
|
|
}
|
|
|
|
test "switch on integer with else capturing expr" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var x: i32 = 5;
|
|
switch (x + 10) {
|
|
14 => @panic("fail"),
|
|
16 => @panic("fail"),
|
|
else => |e| try expect(e == 15),
|
|
}
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "else prong of switch on error set excludes other cases" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
try expectError(error.C, bar());
|
|
}
|
|
const E = error{
|
|
A,
|
|
B,
|
|
} || E2;
|
|
|
|
const E2 = error{
|
|
C,
|
|
D,
|
|
};
|
|
|
|
fn foo() E!void {
|
|
return error.C;
|
|
}
|
|
|
|
fn bar() E2!void {
|
|
foo() catch |err| switch (err) {
|
|
error.A, error.B => {},
|
|
else => |e| return e,
|
|
};
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch prongs with error set cases make a new error set type for capture value" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
try expectError(error.B, bar());
|
|
}
|
|
const E = E1 || E2;
|
|
|
|
const E1 = error{
|
|
A,
|
|
B,
|
|
};
|
|
|
|
const E2 = error{
|
|
C,
|
|
D,
|
|
};
|
|
|
|
fn foo() E!void {
|
|
return error.B;
|
|
}
|
|
|
|
fn bar() E1!void {
|
|
foo() catch |err| switch (err) {
|
|
error.A, error.B => |e| return e,
|
|
else => {},
|
|
};
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "return result loc and then switch with range implicit casted to error union" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
try expect((func(0xb) catch unreachable) == 0xb);
|
|
}
|
|
fn func(d: u8) anyerror!u8 {
|
|
return switch (d) {
|
|
0xa...0xf => d,
|
|
else => unreachable,
|
|
};
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch with null and T peer types and inferred result location type" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest(c: u8) !void {
|
|
if (switch (c) {
|
|
0 => true,
|
|
else => null,
|
|
}) |v| {
|
|
_ = v;
|
|
@panic("fail");
|
|
}
|
|
}
|
|
};
|
|
try S.doTheTest(1);
|
|
try comptime S.doTheTest(1);
|
|
}
|
|
|
|
test "switch prongs with cases with identical payload types" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const Union = union(enum) {
|
|
A: usize,
|
|
B: isize,
|
|
C: usize,
|
|
};
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
try doTheSwitch1(Union{ .A = 8 });
|
|
try doTheSwitch2(Union{ .B = -8 });
|
|
}
|
|
fn doTheSwitch1(u: Union) !void {
|
|
switch (u) {
|
|
.A, .C => |e| {
|
|
try expect(@TypeOf(e) == usize);
|
|
try expect(e == 8);
|
|
},
|
|
.B => |e| {
|
|
_ = e;
|
|
@panic("fail");
|
|
},
|
|
}
|
|
}
|
|
fn doTheSwitch2(u: Union) !void {
|
|
switch (u) {
|
|
.A, .C => |e| {
|
|
_ = e;
|
|
@panic("fail");
|
|
},
|
|
.B => |e| {
|
|
try expect(@TypeOf(e) == isize);
|
|
try expect(e == -8);
|
|
},
|
|
}
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch on pointer type" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
const X = struct {
|
|
field: u32,
|
|
};
|
|
|
|
const P1 = @as(*X, @ptrFromInt(0x400));
|
|
const P2 = @as(*X, @ptrFromInt(0x800));
|
|
const P3 = @as(*X, @ptrFromInt(0xC00));
|
|
|
|
fn doTheTest(arg: *X) i32 {
|
|
switch (arg) {
|
|
P1 => return 1,
|
|
P2 => return 2,
|
|
else => return 3,
|
|
}
|
|
}
|
|
};
|
|
|
|
try expect(1 == S.doTheTest(S.P1));
|
|
try expect(2 == S.doTheTest(S.P2));
|
|
try expect(3 == S.doTheTest(S.P3));
|
|
try comptime expect(1 == S.doTheTest(S.P1));
|
|
try comptime expect(2 == S.doTheTest(S.P2));
|
|
try comptime expect(3 == S.doTheTest(S.P3));
|
|
}
|
|
|
|
test "switch on error set with single else" {
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var some: error{Foo} = error.Foo;
|
|
try expect(switch (some) {
|
|
else => blk: {
|
|
break :blk true;
|
|
},
|
|
});
|
|
}
|
|
};
|
|
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "switch capture copies its payload" {
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var tmp: union(enum) {
|
|
A: u8,
|
|
B: u32,
|
|
} = .{ .A = 42 };
|
|
switch (tmp) {
|
|
.A => |value| {
|
|
// Modify the original union
|
|
tmp = .{ .B = 0x10101010 };
|
|
try expectEqual(@as(u8, 42), value);
|
|
},
|
|
else => unreachable,
|
|
}
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "capture of integer forwards the switch condition directly" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn foo(x: u8) !void {
|
|
switch (x) {
|
|
40...45 => |capture| {
|
|
try expect(capture == 42);
|
|
},
|
|
else => |capture| {
|
|
try expect(capture == 100);
|
|
},
|
|
}
|
|
}
|
|
};
|
|
try S.foo(42);
|
|
try S.foo(100);
|
|
try comptime S.foo(42);
|
|
try comptime S.foo(100);
|
|
}
|
|
|
|
test "enum value without tag name used as switch item" {
|
|
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
|
|
|
const E = enum(u32) {
|
|
a = 1,
|
|
b = 2,
|
|
_,
|
|
};
|
|
var e: E = @as(E, @enumFromInt(0));
|
|
switch (e) {
|
|
@as(E, @enumFromInt(0)) => {},
|
|
.a => return error.TestFailed,
|
|
.b => return error.TestFailed,
|
|
_ => return error.TestFailed,
|
|
}
|
|
}
|
|
|
|
test "switch item sizeof" {
|
|
const S = struct {
|
|
fn doTheTest() !void {
|
|
var a: usize = 0;
|
|
switch (a) {
|
|
@sizeOf(struct {}) => {},
|
|
else => return error.TestFailed,
|
|
}
|
|
}
|
|
};
|
|
try S.doTheTest();
|
|
try comptime S.doTheTest();
|
|
}
|
|
|
|
test "comptime inline switch" {
|
|
const U = union(enum) { a: type, b: type };
|
|
const value = comptime blk: {
|
|
var u: U = .{ .a = u32 };
|
|
break :blk switch (u) {
|
|
inline .a, .b => |v| v,
|
|
};
|
|
};
|
|
|
|
try expectEqual(u32, value);
|
|
}
|
|
|
|
test "switch capture peer type resolution" {
|
|
const U = union(enum) {
|
|
a: u32,
|
|
b: u64,
|
|
fn innerVal(u: @This()) u64 {
|
|
switch (u) {
|
|
.a, .b => |x| return x,
|
|
}
|
|
}
|
|
};
|
|
|
|
try expectEqual(@as(u64, 100), U.innerVal(.{ .a = 100 }));
|
|
try expectEqual(@as(u64, 200), U.innerVal(.{ .b = 200 }));
|
|
}
|
|
|
|
test "switch capture peer type resolution for in-memory coercible payloads" {
|
|
const T1 = c_int;
|
|
const T2 = @Type(@typeInfo(T1));
|
|
|
|
comptime assert(T1 != T2);
|
|
|
|
const U = union(enum) {
|
|
a: T1,
|
|
b: T2,
|
|
fn innerVal(u: @This()) c_int {
|
|
switch (u) {
|
|
.a, .b => |x| return x,
|
|
}
|
|
}
|
|
};
|
|
|
|
try expectEqual(@as(c_int, 100), U.innerVal(.{ .a = 100 }));
|
|
try expectEqual(@as(c_int, 200), U.innerVal(.{ .b = 200 }));
|
|
}
|
|
|
|
test "switch pointer capture peer type resolution" {
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const T1 = c_int;
|
|
const T2 = @Type(@typeInfo(T1));
|
|
|
|
comptime assert(T1 != T2);
|
|
|
|
const U = union(enum) {
|
|
a: T1,
|
|
b: T2,
|
|
fn innerVal(u: *@This()) *c_int {
|
|
switch (u.*) {
|
|
.a, .b => |*ptr| return ptr,
|
|
}
|
|
}
|
|
};
|
|
|
|
var ua: U = .{ .a = 100 };
|
|
var ub: U = .{ .b = 200 };
|
|
|
|
ua.innerVal().* = 111;
|
|
ub.innerVal().* = 222;
|
|
|
|
try expectEqual(U{ .a = 111 }, ua);
|
|
try expectEqual(U{ .b = 222 }, ub);
|
|
}
|
|
|
|
test "inline switch range that includes the maximum value of the switched type" {
|
|
const inputs: [3]u8 = .{ 0, 254, 255 };
|
|
for (inputs) |input| {
|
|
switch (input) {
|
|
inline 254...255 => |val| try expectEqual(input, val),
|
|
else => |val| try expectEqual(input, val),
|
|
}
|
|
}
|
|
}
|
|
|
|
test "nested break ignores switch conditions and breaks instead" {
|
|
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
|
|
|
|
const S = struct {
|
|
fn register_to_address(ident: []const u8) !u8 {
|
|
const reg: u8 = if (std.mem.eql(u8, ident, "zero")) 0x00 else blk: {
|
|
break :blk switch (ident[0]) {
|
|
0x61 => (try std.fmt.parseInt(u8, ident[1..], 0)) + 1,
|
|
0x66 => (try std.fmt.parseInt(u8, ident[1..], 0)) + 1,
|
|
else => {
|
|
break :blk 0xFF;
|
|
},
|
|
};
|
|
};
|
|
return reg;
|
|
}
|
|
};
|
|
// Originally reported at https://github.com/ziglang/zig/issues/10196
|
|
try expect(0x01 == try S.register_to_address("a0"));
|
|
}
|